0

I have a list such as this:

l = ['(7 - 3)', '7 - 6', '(a + 13)']

I want to remove any expression that does NOT contain the letter "a" therefore the only expression that would be left is ['(a+13)']. So far I have tried this:

for i in range(len(l)):
    if "a" not in l[i]:
        l.pop(i)
else:
    print(l[i])

However I am getting a list index out of range error, and do not know how to fix this.
Could anyone help resolve this?

martineau
  • 119,623
  • 25
  • 170
  • 301
  • When you pop an element from the list you decrease the size of the list while the for loop keeps the old length. I would suggest to use a second list to pop from. – Headhunter Xamd Feb 15 '17 at 17:17
  • I would suggest a new approach and create a new list and .append() items that __do__ contain 'a': new = [] # you were using 'l' for 'currentlist' for i in currentlist: if "a" in i: new.append(i) –  Feb 15 '17 at 18:18

4 Answers4

3

l.pop() removes elements from the list, so your list is getting smaller but you are not adjusting your iteration.

>>> x = [1,2,3]
>>> x.pop(0)
1
>>> x
[2, 3]
>>> x.pop(1)
3
>>> x
[2]
>>> x.pop(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: pop index out of range

I would suggest you take a different approach. You could iterate over the elements of the list directly and print the ones that have "a" in them.

for i in l:
  if "a" in i:
     print(i)

If you need the list to have only the elements that have "a" in them at the end of your iteration, perhaps you would like to add those items to a new list.

things_with_a_in_them = []
for i in l:
  if "a" in i:
    things_with_a_in_them.append(i)
    print(i)

If you want it to be terser...

things_with_a_in_them = [i for i in l if "a" in i]
map(print, things_with_a_in_them)

Have fun playing around with different approaches.

2rs2ts
  • 10,662
  • 10
  • 51
  • 95
1

Never structurally manipulate a list while iterating over it! Use a conditional comprehension

l = [x for x in l if 'a' in x]

or filter:

l = filter(lambda x: 'a' in x, l)
# in Python3, you will have to convert the filter object to a list
# l = list(filter(lambda x: 'a' in x, l)) 
user2390182
  • 72,016
  • 6
  • 67
  • 89
1

The problem is len(l) returns 3, but as soon as you pop an item, your list becomes shorter. Easiest thing to do (assuming your list isn't prohibitively giant) would be to just write a new list:

l_new = [i for i in l if "a" in i]
Marc
  • 56
  • 3
0

If you don't want to create a new list, and keep your logic with the pop, you would have to check for the len(l) everytime, you can do that by:

l = ['(7 - 3)', '7 - 6', '(a + 13)']

i = 0
while i < len(l):
    if "a" not in l[i]:
        l.pop(i)
    else:
        print(l[i])
        i += 1

But as others have aswered, it would be better to create a new list with list comprehension