0

I'm not sure why my list is not deleting every char that is indexed based on a second List. Below is the code:

L1 = ['e', 'i', 'l', 'n', 's', 't']
L2 = ['e', 'i', 'l', 'n', 's', 't']

for n_item in range(len(L1)):
    if L1[n_item] in L2:
     del L2[n_item]

Below is the error that I'm getting:

 Traceback (most recent call last):
 File "<pyshell#241>", line 3, in <module>
 del L2[n_item]
 IndexError: list assignment index out of range

Thanks for any help ....

suffa
  • 3,606
  • 8
  • 46
  • 66
  • also related: http://stackoverflow.com/questions/7573115/delete-item-from-list-in-python-while-iterating-over-it?rq=1 – mgilson Apr 05 '13 at 19:48

3 Answers3

5

As you remove the earlier items, the list becomes shorter, so the later indicies don't exist. This is a symptom of iterating by index in Python - which is a terrible idea. It's not how Python is designed and will generally make unreadable, slow, inflexible code.

Instead, use a list comprehension to construct a new list:

[item for item in L1 if item not in L2]

Note that if L2 is large, it might be worth making it a set first, as membership tests on a set are much quicker.

Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • 2
    And, if necessary, you can also replace the old list with the new one in place: `L2[:] = [ ... ]`. This keeps things consistent with what OP is trying to do, but also removes the penalty of shifting the elements after each `del`. – mgilson Apr 05 '13 at 19:51
2

Each time you delete an element at an index, the list is changed.

>>> items = ['a', 'b', 'c', 'd']
>>> len(items)
4
>>> items[1]
'b'
>>> del items[1]
>>> items[1]
'c'
>>> len(items)
3

whats causing your error is that the len of the list is changed when you delete the item, however, this doesn't update the range that the for loop is working over.

Additionally, if you delete an element then increase the index, it's really as if you're increasing the index by 2, since everything gets shifted left by one index.

The best solution to this would be a list comprehension as Lattyware suggested. Your for loop can be replaced with

L1 = [item for item in L1 if item not in L2]
Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
1

If you care only about removing specific values from the list (and don't care about indexes, order etc.):

L1 = ['e', 'i', 'l', 'n', 's', 't']
L2 = ['e', 'i', 'l', 'n', 's', 't']

for item in L1:
    try:
        L2.remove(item)
    except ValueError:
        pass

print(L2) gives: []

Piotr Hajduga
  • 608
  • 4
  • 13