Using list comprehension to keep items not in second list - python

I am trying to use list comprehension to remove a number of items from a list by just keeping those not specified.
For example if I have 2 lists a = [1,3,5,7,10] and b = [2,4] I want to keep all items from a that are not at an index corresponding to a number in b.
Now, I tried to use y = [a[x] for x not in b] but this produces a SyntaxError.
y = [a[x] for x in b] works fine and keeps just exact the elements that i want removed.
So how do I achieve this? And on a side note, is this a good way to do it or should I use del?

You can use enumerate() and look up indexes in b:
>>> a = [1, 3, 5, 7, 10]
>>> b = [2, 4]
>>> [item for index, item in enumerate(a) if index not in b]
[1, 3, 7]
Note that to improve the lookup time, better have the b as a set instead of a list. Lookups into sets are O(1) on average while in a list - O(n) where n is the length of the list.

Guess you're looking for somthing like :
[ x for x in a if a.index(x) not in b ]
Or, using filter:
filter(lambda x : a.index(x) not in b , a)

Try this it will work
[j for i,j in enumerate(a) if i not in b ]

after this:
y = [a[x] for x in b]
just add:
for x in y:
a.remove(x)
then you end up with a stripped down list in a

Related

Filter nested list with list comprehension based on other list in python

I have two lists like this:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
I would now like to filter list a, to keep only the items which contain the items in list b. So the desired output would look like this:
[[1,2,3],[2,3,4]]
I have tried some nested list comprehensions, which I could think of, but could not get the desired output. Any advice is appreciated.
you could try something like this :
print([i for i in a if any(map(i.__contains__,b))])
>>> [[1, 2, 3], [2, 3, 4]]
I would try something like this:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
result = [lst for lst in a if any(x in lst for x in b)]
A combination of list comprehension and sets would yield the wanted result. Note; I assume that repeated items and ordering is not of interest, if this is the case - a set won't work since it ignores ordering and only allows unique items.
A simple list comprehension would do, like below
filter_items = set(filter_items)
[sublist for sublist in original_list if not set(sublist).isdisjoint(filter_items)]
There's mainly one interesting part of this list comprehension, namely the if not set(sublist).isdisjoint(filter_items). Here you only keep the sublist if the set of sublist is not disjoint of the set filter_items i.e. none of the filter_items is in the sublist.
for your given example the provided answer would yield the following:
>>> a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
>>> b = set([1,2])
>>> [sublist for sublist in a if not set(sublist).isdisjoint(b)]
[[1, 2, 3], [2, 3, 4]]
Using a set approach the in can be mimic with an intersection:
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
b_as_set = set(b)
out = [l for l in a if b_as_set.intersection(l)]
# [[1, 2, 3], [2, 3, 4]]
I would try something like this.
a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
b = [1,2]
print([lst for lst in a if any([item in b for item in lst])])

Get element from list of list based on index from another list

I would like to retrieve specific elements within a list of lists without using list comprehension, loops, or any iterative approach in Python.
For example, given this list:
[[1,2,3,4],[3,4],[5,6,7]]
and this vector:
[0,0,1]
I would like to retrieve the 0th element on the 0th list, the 0th element of the 1st list, and the 1st element of the 2nd list:
[1,2,3,4][0] -> 1
[3,4][0] -> 3
[5,6,7][1] -> 6
Which should give this result:
[1,3,6]
Is this possible in python?
This is an alternate:
x = [[1,2,3,4],[3,4],[5,6,7]]
y = [0,0,1]
res = []
for i in range(len(x)):
res.append(x[i][y[i]])
Using a list comprehension with zip() is one of the most Pythonic way to achieve this:
>>> my_list = [[1,2,3,4],[3,4],[5,6,7]]
>>> my_vector = [0,0,1]
>>> [x[i] for x, i in zip(my_list, my_vector)]
[1, 3, 6]
However, since OP can not use list comprehension, here's an alternative using map() with lambda expression as:
>>> list(map(lambda x, y: x[y], my_list, my_vector))
[1, 3, 6]
In the above solution, I am explicitly type-casting the object returned by map() to list as they return the iterator. If you are fine with using iterator, there's no need to type-cast.
you can use zip
l = [[1,2,3,4],[3,4],[5,6,7]]
i = [0,0,1]
op = []
for index, element in zip(i, l):
op.append(element[index])
output
[1, 3, 6]
using map you can do this way
a = [[1,2,3,4],[3,4],[5,6,7]]
b = [0, 0, 1]
result = list(map(lambda x,y: x[y], a,b))
print(result)
output
[1, 3, 6]

Running an operation on each 2 consecutive variables in Python?

I have a Python list like:
mylist = [1,2,3,4,5,6,7,8]
And I want to run an operation on each two consecutive variables. For example I want to sum each two consecutive variables in the list and put them into another list:
newlist = [1+2, 3+4, 5+6, 7+8]
But how can I do that in Python? I didn't know where to start. Should I use two nested for loops, or enumerate, or zip function? I am confused.
My favorite way to do this is with an explicit list_iterator.
itr = iter(mylist)
newlist = [x + y for x, y in zip(itr, itr)]
zip advances the iterator by two elements each time it yields a pair. The benefit of using an iterator over slicing is that it doesn't require you to make two half-copies of the list before zipping.
If you don't like two lines, Python 3.8 can fold the assignment into an expression:
from operator import add
newlist = list(map(add, (i:=iter(mylist)), i))
(For some reason, you can't use an assignment expression in a list comprehension.
[x + y for x, y in zip((i:=iter(mylist)), i)]
is a syntax error, but
t = zip((i:=iter(mylist)), i)
[x + y for x, y in t]
is fine. I suspect it has something to do with scoping, but I don't know the technical details.)
Solution with zip():
out = [a+b for a, b in zip(mylist[::2], mylist[1::2])]
print(out)
Prints:
[3, 7, 11, 15]
The range() function defaults to increment the sequence by 1, but one can increment the value by adding a third parameter - range(start, stop, step_size).
You can try this:-
res = [mylist[i]+mylist[i+1] for i in range(0,len(mylist)-1, 2)]
print(res)
Output:-
[3, 7, 11, 15]
You can use this list comprehension:
mylist = [1,2,3,4,5,6,7,8]
mylist =[n+mylist[i-1] for i,n in enumerate(mylist) if i%2]
print(mylist)
Output:
[3, 7, 11, 15]

Access elements from two sublist without using a nested for loop in python

for example :
list = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
and I want to compare the first element of two consecutive sublists in every iteration of for loop.
How should I write the for loop?
I have tried this following code :
for x in list:
print(x[0])
print(x+1[0])
I know the use of (x+1[0]) is completely illogical. But what should I use at this place? Any suggestions?
Like comparing(any type of mathematical comparison) 1st elements of list1 & list2, list3 & list4.
You can use zip() to pair off consecutive lists by passing slices to zip. To pair them off at an offset like: [0, 1], [1, 2], [2, 3] you could use:
zip(l, l[1:])
To pair them off as pairs (rather than repeating the last one like [0, 1], [2, 3]) you could use:
zip(l[::], [1:1])
In your example that would look like:
l = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
for l1, l2 in zip(l[::2], l[1::2]):
print(l1[0], l2[0])
Prints:
1 5
9 13
Try:
for x in list1:
for y in list1:
if x[0] == y[0]:
print(x[0],y[0])
Now if you don't want to compare the same elements (which the above code does):
for x in list1:
for y in [i for i in list1 if i!=x]:
if x[0] == y[0]:
print(x[0],y[0])
Or you could print like:
for x in list1:
for y in [i for i in list1 if i!=x]:
if x[0] == y[0]:
print(x ,"and", y , 'have the same elements first')
Here:
list1 = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
following code will genrate first element from every sublist. Tweak it according to your need
lst = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
for i in range(len(lst[0])):
for j in range(len(lst)):
print(lst[j][i], end=" ")
print()

Converting float to integers in a specific sublist

Let's make this short.
I have a list of lists, for example
a = [[1.0, 2.0], [6, 8]]
What I would like to do, is to convert all values of the first sublist into integers, so the array will be
a = [[1, 2], [6, 8]]
Can you please tell me how to do it? I struggled with map already, yet I can't seem to find the correct usage. Thanks in advance.
You can use a nested list comprehension:
[[int(y) for y in x] for x in a]
Or with map:
[list(map(int, x)) for x in a]
You can use list comprehension for the first list (that needs transformation), and add the second list (which you don't need to change).
print([[int(aa) for aa in a[0]], a[1]])
Out[46]: [[1, 2], [6, 8]]
Unlike the other solutions, this does not change the 2nd part of the list in any way.
If you only want to change the first delivery list, an option
[a for a in map(lambda n, x: list(x if n else int(x) for x in a[n]), (0, 1), a)]
You can assign it to a variable and then print to the screen.
b = [a for a in map(lambda n, x: list(x if n else int(x) for x in a[n]), (0, 1), a)]
print(b)
remembering that it will only transform the values ​​in the left list

Categories