This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 6 years ago.
I have created a list full of "coordinates" in Python: L1 = [(1,2), (5,6), (-1,-2), (1,-2), etc..].
If I wanted to remove all items in the list which contained negative numbers, how would I do this?
I've tried:
for (a,b) in L1:
if a < 0 or b < 0:
L1.remove(a,b)
But it isn't working. Would very much appreciate any help.
Jack
You cannot change something while you're iterating it. The results are weird and counter-intuitive, and nearly never what you want. In fact, many collections explicitly disallow this (e.g. sets and dicts).
Instead, iterate over a copy (for e in a[:]: ...) or, instead of modifying an existing list, filter it to get a new list containing the items you want ([e for e in a if ...]). Note that in many cases, you don't have to iterate again to filter, just merge the filtering with the generation of the data.
L2 = []
for (a,b) in L1:
if a >= 0 and b >= 0:
L2.append((a,b))
L1 = L2
print L1
You can filter using a list comprehension:
>>> coords = [(1, 2), (5, 6), (-1, -2), (1, -2)]
>>> [coord for coord in coords
... if not any(number < 0 for number in coord)]
[(1, 2), (5, 6)]
Related
This question already has answers here:
Get unique items from list of lists? [duplicate]
(3 answers)
Closed 2 years ago.
I have a list of lists of tuples:
x = [[(0,0),(0,1)],[(1,2),(2,3)],[(0,0),(0,1)],[(1,2),(2,3)]]
I want all the unique lists present in the list x
My output should be:
x=[[(0,0),(0,1)],[(1,2),(2,3)]]
I tried using x=list(set(x)) but it gives error: 'list is not hashable', I also tried using numpy.unique but it does not give desired output. How can I implement this?
list as mutable and hence can not be used as an element to a set. However, you can type-cast the list to tuple which are immutable, and then you can get unique elements using set. Here I am using map() to covert all sub-lists to tuple:
>>> x = [[(0,0),(0,1)],[(1,2),(2,3)],[(0,0),(0,1)],[(1,2),(2,3)]]
>>> set(map(tuple, x))
{((1, 2), (2, 3)), ((0, 0), (0, 1))}
To type-cast the set back to list and change back nested tuple to list, you can further use map() as:
>>> list(map(list, set(map(tuple, x))))
[[(1, 2), (2, 3)], [(0, 0), (0, 1)]]
i would do something like this:
x = [[(0,0),(0,1)],[(1,2),(2,3)],[(0,0),(0,1)],[(1,2),(2,3)]]
result = []
for i in x:
if not i in result:
result.append(i)
print(result)
maybe it is not the fastest way but certainly it is the simpler.
Otherwise you can use the most "cool" way, you can use sets. Sets are like lists that don't allow equal elements.
x = x = [[(0,0),(0,1)],[(1,2),(2,3)],[(0,0),(0,1)],[(1,2),(2,3)]]
result = list(map(list,set(map(tuple,x))))
I have something like this in python [[(1,2),(3,7)],[(5,22)],[(4,-1),(-3,34),(41,2)]] and I want to filter the sub lists with "filter" So the condition will be if the sum of all the first element of each tuple in the sub list be greater than 5 and if not delete the sub list.
Maybe you have any idea how can do it ? (without packages or imports)
Thanks
You can use nested list comprehension with a filter condition like this:
sub_lists = [[(1,2),(3,7)],[(5,22)],[(4,-1),(-3,34),(41,2)]]
filtered_sub_lists = [
sub_list for sub_list in sub_lists if sum(values[0] for values in sub_list) > 5
]
print(filtered_sub_lists)
>>> [[(4, -1), (-3, 34), (41, 2)]]
you can use list comprehension
a = [[(1,2),(3,7)],[(5,22)],[(4,-1),(-3,34),(41,2)]]
b = [x for x in a if sum(y for y,_ in x) > 5]
Edited based on comment from azro.
x is each sub array in a, and the sum takes the first element of each sub array and if the total is greater than 5 then x is included in b.
I'm trying to execute a formula on multiple items in parallel which are taken from different lists.
First thing my lists are the following:
l1= [1,2,3]
l2= [4,5,6]
l3= [7,8,9]
Next i need to create new set of lists from my main lists in order to compare each pair of elements inside the list:
newl1 = list(zip(l1, l1[1:])) #outputs [(1,2), (2,3)]
newl2 = list(zip(l2, l2[1:])) #outputs [(4,5), (5,6)]
newl3 = list(zip(l3, l3[1:])) #outputs [(7,8), (8,9)]
Now i want to iterate through all the new set of lists in parallel, with the ability to compare the tuple lists elements:
for pair_of_newl1, pair_of_newl2, pair_of_newl3 in newl1, newl2, newl3:
if pair_of_newl1[0] > pair_of_newl1[1]:
x = pair_of_newl1[0] + pair_of_newl2[1] + pair_of_newl3[1]
print (x)
elif pair_of_newl1[0] < pair_of_newl1[1]:
x = pair_of_newl1[0] - pair_of_newl2[1] - pair_of_newl3[1]
print (x)
Expecting that in first iteration:
pair_of_newl1 = (1,2)
pair_of_newl2 = (4,5)
pair_of_newl3 = (7,8)
Thus being able to compare the items inside them by indexing.
I'm getting the following error:
ValueError: not enough values to unpack (expected 3, got 2)
I was confused, and deleted the last list leaving only two lists to work with:
l1= [1,2,3]
l2= [4,5,6]
newl1 = list(zip(l1, l1[1:])) #outputs [(1,2), (2,3)]
newl2 = list(zip(l2, l2[1:])) #outputs [(4,5), (5,6)]
for pair_of_newl1, pair_of_newl2 in newl1, newl2:
if pair_of_newl1[0] > pair_of_newl1[1]:
x = pair_of_newl1[0] + pair_of_newl2[1]
print (x)
elif pair_of_newl1[0] < pair_of_newl1[1]:
x = pair_of_newl1[0] - pair_of_newl2[1]
print (x)
print (pair_of_newl1, pair_of_newl2) #just to see how the loop works
And i'm getting:
-1
(1, 2) (2, 3)
-1
(4, 5) (5, 6)
So by my understanding pair_of_newl2 is taken as the second item of newl1, but why not newl2 ?
Help please.
You forget to add zip to iterate them:
for pair_of_newl1, pair_of_newl2 in zip(newl1, newl2):
And the result:
-4
(1, 2) (4, 5)
-4
(2, 3) (5, 6)
The error you get is because the line: for pair_of_newl1, pair_of_newl2, pair_of_newl3 in newl1, newl2, newl3 tries to iterate through the three lists, extracting three elements from each. But the newl-lists only have two elements, each. That won't work.
If you want to loop through parallel lists, you may either zip them (which would make the indexing a little more complicated in your case) or you may use an index iterator:
for i in range(len(newl1)): # For index 0 and 1, each of the list has
if newl1[i][0] > newl1[i][1]:
x = newl1[i][0] + newl2[i][1] + newl2[i][1]
print(x)
elif newl1[i][0] > newl1[i][1]:
x = newl1[i][0] - newl2[i][1] - newl2[i][1]
print (x)
This will loop through the two tuples of the three lists and either add the second element of the second and third list to the first element of the first or subtract them.
Is this what you wanted to do?
This question already has answers here:
Create (L[i], L[i+1]) tuple list from list L [duplicate]
(4 answers)
Closed 7 years ago.
I have an array that looks like this
[1,2,3,4,5]
and I would like a list of tuples that looks like this:
[(1,2),(2,3),(3,4),(4,5)]
What is the most convenient way to do this in python?
Thanks!
zip( a[:-1], a[1:] )
see help(zip) or the website documentation of zip.
Since zip limits itself to the shorter sequence,
zip(a, a[1:])
works too.
EDIT:
Steven brought up the interesting point that if a is very long, doing the implicit copy to get the separate pyObject that is a[1:] is problematic. In this case, you might want to use numpy and its options to get a view on the same data with but a offset.
This can be done using list comprehension and list slicing, you iterate over the elements upto len(a) - 1 and on each iteration slice the elements form current_index and the element next to it.
a = [1,2,3,4,5]
b = [tuple(a[i:i+2]) for i in range(len(a)-1)]
print b
>>> [(1, 2), (2, 3), (3, 4), (4, 5)]
This question already has answers here:
Finding max value in the second column of a nested list?
(5 answers)
Closed 10 years ago.
I have an list of list, list = [(1,2,5), (2,8,7),(3,6,9)], and I want to find the biggest number of the third column, so I tried:
zipped = zip(*list)
print max(zipped[2])
But it does not show the biggest number. Anyone know why and a solution?
Works on all newer Pythons:
>>> li = [(1,2,5), (2,8,7),(3,6,9)]
>>> max(l[2] for l in li)
9
If you have text:
>>> li = [('1','2','5'), ('2','8','7'),('3','6','9')]
>>> max(int(l[2]) for l in li)
9
And works even if the source is an iterator / generator. This is on Py3.3 where zip returns an iterator:
>>> gli=(e for e in li)
>>> max(int(l[2]) for l in gli)
9
>>> max(int(l[2]) for l in zip(*li))
9
Works for me on python2.7.
>>> l = [(1,2,5),(2,8,7),(3,6,9)]
>>> zip(*l)
[(1, 2, 3), (2, 8, 6), (5, 7, 9)]
>>> max(zip(*l)[2])
9
Another option:
max(l,key=lambda x:x[2])[2]
or if you prefer itemgetter:
from operator import itemgetter
max(l,key=itemgetter(2))[2]
This is probably more efficient in terms of memory and it'll work on python3.x where zip no longer returns a list.
The key here is that it allows you to get the full tuple that is the biggest (biggest determined by the 3rd element) and then you just pull the correct element out of there if you want it.