0

The context doesn't matter too much, but I came across the problem that while trying to pop dict objects from a list, it wouldn't delete all of them. I'm doing this to filter for certain values in the dict objects, and I was left with things that should have been removed. Just to see what would happen, I tried deleting every item in the list called accepted_auctions (shown below), but it did not work.

for auction in accepted_auctions:
    accepted_auctions.pop(accepted_auctions.index(auction))

print(len(accepted_auctions))

When I tested this code, print(len(accepted_auctions)) printed 44 into the console.

What am I doing wrong?

BappoHotel
  • 52
  • 10
  • 1
    You're modifying a list that you're iterating over, which causes the iterator to skip items since the indices are shifting underneath it. (Also, the whole thing with `.index` is needlessly complicated and error-prone for entirely unrelated reasons.) If your intent is to empty the list, just do `accepted_auctions.clear()`. – Samwise Dec 03 '22 at 22:51
  • @Samwise My intent, however, is not to clear, but only to remove certain items based on the contents of those items. Emptying the whole list was just a demonstration. How would I go about removing only certain items from a list while iterating through it? – BappoHotel Dec 03 '22 at 22:54
  • You can't pop item(s) from the array (list) you are iterating over. – O_o Dec 03 '22 at 22:54
  • @BappoHotel, create a second copy. What you want to keep, take them to the other list and when you are done, just swap the list like `accepted_auctions = new_autctions`. I would have done this. It seems cleaner to me. – O_o Dec 03 '22 at 22:55
  • @O_o Makes sense, put this in an answer and I'll accept it for rep. Thanks. – BappoHotel Dec 03 '22 at 22:57
  • 1
    It's cool, The answer on your post says the same. You can accept that. @BappoHotel – O_o Dec 03 '22 at 22:59
  • Alternatively, you can loop through your list in reverse order, and delete the required elements as you go (the reverse order prevents deletion from messing up the iteration). – Swifty Dec 03 '22 at 23:02

1 Answers1

2

Modifying a list as you iterate over it will invalidate the iterator (because the indices of all the items are changing as you remove items), which in turn causes it to skip items. Don't do that.

The easiest way to create a filtered list is via a list comprehension that creates a new list, e.g.:

accepted_auctions = [a for a in accepted_auctions if something(a)]

Here's a simple example using a list comprehension to filter a list of ints to only the odd numbers:

>>> nums = list(range(10))
>>> nums
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> nums = [n for n in nums if n % 2]
>>> nums
[1, 3, 5, 7, 9]
Samwise
  • 68,105
  • 3
  • 30
  • 44