Skip to content Skip to sidebar Skip to footer

Python Remove Element In For Loop

[Notice: Even use a temporary array (not modifying loop array), the code didn't give the right answer for list b.] Remove the odd numbers from a list, see below for codes. Why it w

Solution 1:

numbers_buf = numbers[:] #  make a copy not a referencedefpurify(numbers):
    numbers_buf = numbers[:]
    for item in numbers:
        if item % 2:
            numbers_buf.remove(item)
    return numbers_buf

manipulating/removing elements while you iterate over a list will change the index of elements, numbers_buf = numbers creates a reference to the numbers list, basically a pointer to the same object so remove from one, remove from both.

Using numbers[:] creates a copy/new object.

Run the following function to help make it clear, see how 3 and 4 somehow did a runner:

def purify(numbers):
    numbers_buf = numbers
    should_be = numbers[:]
    for ind, item in enumerate(numbers):
        print("{} should be at {}, is at {}".format(item,should_be.index(item),ind))
        if item % 2:
            numbers_buf.remove(item)
    return numbers_buf
print(purify([4,5,4,7,3,1]))

if you did want to use a list comp to modify the original object:

def purify(numbers):
    numbers[:] = [x for x in numbers ifnot x % 2]
    return numbers

You can also use reversed:

defpurify(numbers):
    for item inreversed(numbers):
        if item % 2:
            numbers.remove(item)
    return numbers

Solution 2:

This has been asked many times, look at Modifying list while iterating

You should really be doing:

even = [a for a in numbers if a%2 == 0]

Solution 3:

You are doing two things that you probably should not, as both of them are asking for trouble.

  1. Never, ever, ever add to or remove items from an array while you're iterating over it. This will confuse both Python and you and almost certainly not achieve the desired result.

  2. You really shouldn't be modifying the array in place anyway. The function doesn't get a copy of the array; it's modifying the actual array passed in by the caller. This is likely to be surprising behavior to everyone involved:

    a = [1,2,3,4]
    print purify(a)        #=> [2, 4]print a                #=> [2, 4]

You should construct and return a new array instead, and perhaps change the function name to indicate that (similar to the sort and sorted built-ins):

defpurified(a):
  return [n for n in a if n % 2 == 0]

a = [1,2,3,4]
print purified(a)      #=> [2, 4]print a                #=> [1, 2, 3, 4]

Solution 4:

Your problem stems from the fact that you are not looping over a different list, like you want to be. You want to avoid deleting something from a list while looping over it, which is why you created a new list with numbers_buf = numbers

However, note that no new list was created:

In [73]: numbers = list(range(10))

In [74]: numbers
Out[74]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [75]: id(numbers)
Out[75]: 4469310792

In [76]: numbers_buf = numbers

In [77]: id(numbers)
Out[77]: 4469310792

In [78]: id(numbers_buf)
Out[78]: 4469310792

In [79]: id(numbers_buf) == id(numbers)
Out[79]: True

In [80]: numbers
Out[80]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [81]: numbers_buf
Out[81]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [82]: numbers.append(10)

In [83]: numbers_buf
Out[83]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Notice in the end, when I append 10 to numbers, it gets appended to numbers_buf as well. This is because python doesn't create a new list with numbers in them when you do numbers_buf = numbers; It simply creates the name numbers_buf and makes it point to the exact same structure that numbers points to (this is what all that id(numbers) stuff shows). You could solve this problem as follows:

In [84]: numbers_buf_new = numbers[:]

In [85]: id(numbers_buf_new)
Out[85]: 4469329032In [86]: id(numbers_buf_new) == id(numbers)
Out[86]: FalseIn [87]: numbers
Out[87]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

In [88]: numbers_buf_new
Out[88]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

In [89]: numbers.append(11)

In [90]: numbers
Out[90]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

In [91]: numbers_buf_new
Out[91]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Solution 5:

If you want to retain using remove method and return the same list, you can try this:

defpurify(numbers):

for item in numbers:
    if item % 2 == 1:
        count = numbers.count(item)
        for i inrange(count):
            numbers.remove(item)
return numbers

Post a Comment for "Python Remove Element In For Loop"