2

That code should clear list 'bag' out of numbers. but where number follows a number it doesn't work right. For example 8 after 7.

bag = ['apples', 1,'bananas', 'potatoes', 'tomatoes',2, 'chary',3, 'mo4ka', 7,8, 'candies', 'Main_TX']
list_n = []
x = 0
for i in bag:
    if isinstance(i, int):
        list_n.append(i)
        bag.pop(x)
    x+=1

print(list_n)
print(bag)

result:

[1, 2, 3, 7]
['apples', 'bananas', 'potatoes', 'tomatoes', 'chary', 'mo4ka', 8, 'candies', 'Main_TX']
idjaw
  • 25,487
  • 7
  • 64
  • 83
zero
  • 71
  • 5

2 Answers2

4

Don't try to modify a list while you are iterating over it.

list_n = []
new_bag = []
for x in bag:
    # which_list = list_n if isinstance(x, int) else new_bag
    # which_list.append(x)
    if isinstance(x, int):
        list_n.append(x)
    else:
        new_bag.append(x)
bag = new_bag
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Thank for your respond. I was thinking same way about overcoming this obstacle with: and it work well. but this behavior of initial cod is odd to me, and looks like a bug. ` bag = ['apples', 1,'bananas', 'potatoes', 'tomatoes',2, 'chary',3, 'mo4ka', 7,8, 'candies', 'Main_TX'] list_n = [] list_a = [] for i in bag: if isinstance(i, int): list_n.append(i) else: list_a.append(i) print(list_n) print(list_a) print(bag) ` – zero Nov 05 '16 at 20:06
1

You are modifying your list while iterating. This will lead to unexpected behaviour.

Instead you could use list comprehensions:

list_n = [e for e in bag if isinstance(e, int)]
bag = [e for e in bag if not isinstance(e, int)]

The specific reason why your code doesn't work is that every time you remove an element with bag.pop(x) the following items in the list get shifted back by one index. However, the iterator that is used by the for .. in loop can't know about this shift and therefore when it calls its next() function it's essentially going to skip one element.

If you add a print(i) directly after the head of the loop you will see that every time a number is popped from the list the following list entry is skipped in the for .. in loop (regardless of whether it was a number or not). If it wasn't a number you just don't notice it, because strings are supposed to stay in the list anyway.

Community
  • 1
  • 1
Keiwan
  • 8,031
  • 5
  • 36
  • 49
  • 1
    List comprehensions are faster alternatives to `map` because `map` often requires a user-defined function to wrap the operation applied to each item. If you are simply filtering a list, having to iterate over the list twice (or more) is going to be slower than writing single `for` loop. – chepner Nov 05 '16 at 19:25
  • @chepner That is definitely true and if performance is a concern I would also go with the single loop option myself. However, as long as the list is not too big or performance isn't an issue, the difference in speed isn't really going to affect the overall runtime. – Keiwan Nov 05 '16 at 20:08
  • "unexpected behavior" is exactly what got me. it looks strait forward to me. and works fine all the time, except when number fallows number. And that kinda odd. – zero Nov 05 '16 at 20:14
  • @zero I've added some additional explanation about the "unexpected behaviour" and the fact that it actually never works, but you just don't notice it because it seems to be working. – Keiwan Nov 05 '16 at 20:29