I have the two lists below:
list1 = [(1, 'A'), (2, 'B'), (3, '?'), (4, 'T'), (5, 'A'), (6, 'B'), (7, '?'), (8, 'T')]
list2 = [(2, 'D'), (6, 'E'), (7, '!'), (10, 'T')]
I need to remove from list1
the elements in common with list2
that are in first position. So, I've used the for loop below:
for x in list1:
id_list1 = x[0]
for y in list2:
id_list2 = y[0]
if id_list1 == id_list2:
list1.remove(x)
The output is: [(1, 'A'), (3, '?'), (4, 'T'), (5, 'A'), (7, '?'), (8, 'T')]
The result is strange because I see (7, '?')
in list1
but not (2, 'B')
and (6, 'B')
. The last two tuples are correctly removed, but why not (7, '?')
?
The expected output is: [(1, 'A'), (3, '?'), (4, 'T'), (5, 'A'), (8, 'T')]
CodePudding user response:
You can use:
list1 = [(1, "A"), (2, "B"), (3, "?"), (4, "T"), (5, "A"), (6, "B"), (7, "?"), (8, "T")]
list2 = [(2, "D"), (6, "E"), (7, "!"), (10, "T")]
first_items = set(i for i, _ in list2)
list1[:] = [item for item in list1 if item[0] not in first_items]
print(list1)
output:
[(1, 'A'), (3, '?'), (4, 'T'), (5, 'A'), (8, 'T')]
Basically you create a set from first items of the list2
, then with a list comprehension you pick items from list1
whose first items are not appear in that list. list1[:]
does the job in-place.
Set is chosen because of O(1) membership testing. You could use list or tuple if you're dealing with small lists.
But why your own solution doesn't work:
You shouldn't remove something from a list while you're iterating over it:
To fix it, change for x in list1
to for x in list1[:]
. Now you're iterating over a copy of that list.
CodePudding user response:
Try:
list1 = [(1, 'A'), (2, 'B'), (3, '?'), (4, 'T'), (5, 'A'), (6, 'B'), (7, '?'), (8, 'T')]
list2 = [(2, 'D'), (6, 'E'), (7, '!'), (10, 'T')]
for x in list1[:]:
id_list1 = x[0]
for y in list2:
id_list2 = y[0]
if id_list1 == id_list2:
list1.remove(x)
print(list1)
the reason for the weird behaviour is because when u remove an element from list1, elemensts shift to the left so i might skip an ele.