Dicts not being popped from list?

Question:

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?

Asked By: BappoHotel

||

Answers:

It looks like you’re using a for loop to iterate over the list and calling pop on the list at the same time. This is generally not a good idea because the for loop uses an iterator to go through the items in the list, and modifying the list while you’re iterating over it can cause the iterator to become confused and not behave as expected.

One way to fix this is to create a new list that contains only the items that you want to keep, and then replace the original list with the new one. Here’s an example:

# Create an empty list to store the items that we want to keep
filtered_auctions = []

# Iterate over the items in the list
for auction in accepted_auctions:
    # Check if the item meets the criteria for being kept
    if some_condition(auction):
        # If it does, append it to the filtered list
        filtered_auctions.append(auction)

# Replace the original list with the filtered list
accepted_auctions = filtered_auctions

Another way to fix this is to use a while loop instead of a for loop. Here’s an example:

# Keep looping until the list is empty
while accepted_auctions:
    # Pop the first item from the list
    auction = accepted_auctions.pop(0)

    # Check if the item meets the criteria for being kept
    if some_condition(auction):
        # If it does, append it to the filtered list
        filtered_auctions.append(auction)

# Replace the original list with the filtered list
accepted_auctions = filtered_auctions

I hope this helps! Let me know if you have any other questions.

Answered By: blackeyeaquarius

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]
Answered By: Samwise
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.