0

I am confused why this short snippet to remove specific pairs from a list fails:

g = [[7, 11], [7, 8], [3, 10], [3, 8], [8, 9], [11, 10], [11, 2], 
[11, 9]]
u = 3
g_cpy = g
for e in g_cpy:
    if u == e[0]:
        g.remove(e)
print g

It does not remove the entry [3,8], but it does remove [3,10]. What am I missing?

jpp
  • 159,742
  • 34
  • 281
  • 339
Luke Eller
  • 93
  • 6
  • Possible duplicate of [PYTHON remove elements from nested lists](https://stackoverflow.com/questions/19220554/python-remove-elements-from-nested-lists) – jpp Jan 30 '19 at 01:26
  • Possible duplicate of [How to remove items from a list while iterating?](https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating) – Primusa Jan 30 '19 at 01:28
  • Use a list comprehension:`g_cpy = [i for i in g if i[0] != u]` – Primusa Jan 30 '19 at 01:36

2 Answers2

1
g_cpy = g

does not create a copy of the list, but just a reference to the same object which you then modify during iteration. Another issue is that repeated remove calls are bad in terms of time complexity (each call is O(N)). It is better to use a comprehension to build the new list from scratch (overall linear complexity). You can still use that technique and mutate the original list by using slice assignment:

g[:] = [e for e in g if u != e[0]]
user2390182
  • 72,016
  • 6
  • 67
  • 89
0

I think the reason why [3, 8] is not deleted is that

You deleted 3th element in array and e will be the 4th element in g_cpy.

You already deleted [3, 10] in g_cpy so g_cpy's 4th element will be [8, 9] not [3, 8] and this is why [3, 8] isn't deleted.

If you copy list like g_cpy = g it will just copy memory address. So both of them will point same object. If you delete item in g item in g_cpy will also deleted.

If you want to avoid this problem, copy list like g_cpy = g[::]. It will copy entry object to other memory not just copying memory address.

Damotorie
  • 586
  • 7
  • 25