How to remove a list of indices from list - python

I have two lists of lists of the same length in Python 3 as follows:
A = [[0], [0, 1], [0, 1, 2], [0, 1], [0, 1, 2, 3]]
W = [[2, 2], [1, 2, 3], [2, 2, 2, 3], [1, 3, 4, 4], [1, 1, 3, 4]]
Elements of A are indices of elements of W. I would like to remove the elements of W given A. So, in the example, I would like to remove W[0][0], W[1][0], W[1][1], W[2][0], W[2][1], W[2][2], etc.
What I did is this:
for t in range(len(A)):
del W[t][A[t]]
But this gives the following error: TypeError: list indices must be integers or slices, not list

Unlike numpy arrays, you cannot index a list with a list. But you can use a list comprehension for this task:
A = [[0], [0, 1], [0, 1, 2], [0, 1], [0, 1, 2, 3]]
W = [[2, 2], [1, 2, 3], [2, 2, 2, 3], [1, 3, 4, 4], [1, 1, 3, 4]]
res = [[j for i, j in enumerate(w) if i not in a] for a, w in zip(A, W)]
print(res)
[[2], [3], [3], [4, 4], []]
Or, if you are happy using a 3rd party library, numpy syntax is simpler:
import numpy as np
res = [np.delete(i, j).tolist() for i, j in zip(W, A)]

One easy way is to use two nested loops. As you have probably noticed by now, you need two index numbers - one for the list in A and another for the element number of this list. Here is one way to tackle the problem:
A = [[0], [0, 1], [0, 1, 2], [0, 1], [0, 1, 2, 3]]
W = [[2, 2], [1, 2, 3], [2, 2, 2, 3], [1, 3, 4, 4], [1, 1, 3, 4]]
#cycle through list A and keep track of the list number i
for i, a_list in enumerate(A):
#retrieve index from each list in A, start with the highest index to avoid index problems
for j in sorted(a_list, reverse = True):
#delete the element j in list i of W
del W[i][j]
print(W)
#output
#[[2], [3], [3], [4, 4], []]

Related

How to reorder a list composed of lists

I am trying to tranform
[[1, 2, 3], [1, 2]]
into
[[1, 2, 3], [3, 2, 1], [2, 3, 1], [1, 2], [2, 1]]
But instead of the correct output, I am getting this:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2], [1, 2]]
Here is my code
def listReorder(list1):
List2 = []
for list in list1:
listTemp = list
for item in list:
List2.append(listTemp)
t=listTemp.pop()
listTemp.insert(0, t)
return List2
List = [[1, 2, 3], [1, 2]]
listReorder(List)
In your for loop, you are adding the same list again and again, but instead, you should make a copy of the list in the iteration.
def listReorder(list1):
List2 = []
for list in list1:
listTemp = list
for item in list:
List2.append([x for x in listTemp])
t=listTemp.pop()
listTemp.insert(0, t)
return List2
List = [[1, 2, 3], [1, 2]]
listReorder(List)
Output:
[[1, 2, 3], [3, 1, 2], [2, 3, 1], [1, 2], [2, 1]]

Python 3 list of all possible cohesive combinations

Hi I'm trying to make a list of all possible cohesive combinations of another list, so from [0, 1, 2, 3] I'd like to get [[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]. So far I've got this:
def expandArray(arr):
result = []
for x in range(0, len(arr)):
subArray = [arr[x]]
result.append(subArray)
for y in range(x + 1, len(arr)):
subArray.append(arr[y])
result.append(subArray)
return(result)
But this returns: [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [2, 3], [2, 3], [3]].
What am I doing wrong ?
subArray is a list that you modify in your for loop. When you append to it, you do not create a new list, but you modify it, and then put it in the list again, so will in the end get a result with several copies of the same list. Compare this code:
a = []
b = [5]
a.append(b)
b.append(1)
a.append(b)
print(a)
would output:
[[5, 1], [5, 1]]
Here is a way to have your desired output using list slicing:
def get_combs(iterable):
for k, _ in enumerate(iterable):
elm = k
while elm <= len(iterable):
data = iterable[k:elm]
elm += 1
if data:
yield data
combs = list(get_combs([0, 1, 2, 3]))
print(combs)
Output:
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]

How do I iterate over a slice of nested list?

I have this nested list:
nested = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
I wanted to subtract 1 from the first 2 elements of the inner list so I tried it with list comprehension:
nested = [[x - 1 for x in stack[0:2]] for stack in nested]
It did give me back the first 2 elements subtracted by 1 for the inner lists but it removed the last element completely
nested = [[0, 0], [1, 1], [2, 2]]
I thought that by slicing the list, it will not affect the other element. However in this case it didn't work. Can someone explain this to me?
To keep the 3rd element, include it in the list comprehension:
>>> [ [x - 1 for x in stack[0:2]] + stack[2:] for stack in nested ]
[[0, 0, 1], [1, 1, 2], [2, 2, 3]]
The above works for stack of any length.
Or, if stack always has exactly three elements:
>>> [[x-1, y-1, z] for x, y, z in nested]
[[0, 0, 1], [1, 1, 2], [2, 2, 3]]
Or, you can make the changes in place:
>>> for stack in nested: stack[0]-=1; stack[1]-=1
...
>>> nested
[[0, 0, 1], [1, 1, 2], [2, 2, 3]]
Another option is to use numpy which does this sort of slicing naturally
import numpy as np
nested = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]])
nested[:,:2] -= 1
returns
array([[0, 0, 1],
[1, 1, 2],
[2, 2, 3]])
Try it like this:
nested = [[x - 1 if i < 2 else x for i,x in enumerate(stack)] for stack in nested]
This will affect only first two elements keeping the rest as is.
You can use enumerate:
nested = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
new_nested = [[a-1 if i == 0 or i == 1 else a for i, a in enumerate(b)] for b in nested]
Output:
[[0, 0, 1], [1, 1, 2], [2, 2, 3]]
Edit: alternative, with map:
nested = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
new_nested = [map(lambda x:x-1, i[:2])+[i[-1]] for i in nested]
Output:
[[0, 0, 1], [1, 1, 2], [2, 2, 3]]

Compare two lists of lists in Python and find the difference between lists with the same indices

For example, if we have
ListofLists1 = [[0], [0], [1, 3], [1, 4], []]
and
ListofLists2 = [[0, 2], [0, 1, 2, 3], [1, 3, 4], [1, 3, 4], [0, 1, 3]]
and we define
Diff = ListofLists2 - ListofLists1
I would like to have the output in the following form
Diff = [[2], [1,2,3], [4], [3], [0,1,3]]
For the specific kind of work that I am doing, I always expect to find all elements in any list inside ListofLists1 contained inside the corresponding (same index) list in ListofLists2. However, a list inside ListofLists2 may contain elements that are not present inside the corresponding list in ListofLists1.
Zip the two lists together, iterate through them as part of a list comprehension and find the set symmetric difference in each case, setting each resulting set to a list type:
ListofLists1 = [[0], [0], [1, 3], [1, 4], []]
ListofLists2 = [[0, 2], [0, 1, 2, 3], [1, 3, 4], [1, 3, 4], [0, 1, 3]]
[list(set(l1).symmetric_difference(l2)) for l1,l2 in zip(ListofLists1,ListofLists2)]
Gives:
[[2], [1, 2, 3], [4], [3], [0, 1, 3]]
Another solution hit my brain just now. What about
Diff = map( lambda x,y: list(set(x) - set(y)), ListofLists2, ListofLists1 )
This also returns
Diff = [[2], [1,2,3], [4], [3], [0,1,3]]
for
ListofLists1 = [[0], [0], [1, 3], [1, 4], []]
ListofLists2 = [[0, 2], [0, 1, 2, 3], [1, 3, 4], [1, 3, 4], [0, 1, 3]]
Any thoughts on how this method would compare with psychemedia's answer (in terms of speed of implementation for lists which are typically tens of million in length)?

How to split a matrix, represented as a list of list, in half?

If I have a matrix represented as a list of list how do I split it down the middle.
For example
[[1,1,1,1,1,1], ,[2,2,2,2,2,2], ,[3,3,3,3,5,6]]
would be
[[1,1,1],[2,2,2],[3,3,3]]
[[1,1,1],[2,2,2],[3,5,6]]
You can use a list comprehension:
my_list = [[1,1,1,1,1,1], [2,2,2,2,2,2], [3,3,3,3,5,6]]
>>> [[sub_list[:len(sub_list) // 2] for sub_list in my_list],
[sub_list[len(sub_list) // 2:] for sub_list in my_list]]
[[[1, 1, 1], [2, 2, 2], [3, 3, 3]], [[1, 1, 1], [2, 2, 2], [3, 5, 6]]]

Categories

Resources