How to filter a list
Question:
Im writing a simple function to take out any odd numbers from a list and return a list of only the even ones.
def purify(numbers):
for i in numbers:
if i%2!=0:
numbers.remove(i)
return numbers
print(purify([4,5,5,4]))
However, the above returns:
[4, 5, 4]
Why doesn’t the second 5 get removed as it also meets the if condition?
Im looking less for a different method to the problem and more to understand why this happens.
Answers:
When you remove an item, the items that follow get moved one position to the left. This results in the loop skipping some items.
BTW, a more idiomatic way to write that code is
numbers = [num for num in numbers if num % 2 == 0]
>>> listToPurify = [1, 2, 2, 3, 4, 5, 6, 6, 5]
>>> purified = [i for i in listToPurify if i % 2]
>>> purified
[1, 3, 5, 5]
Seems that NPE posted this before me! If you’re confused about list comprehensions, check out here.
If you’d prefer to use a for
loop, you’re going to have to deal with the fact that the length of the list is changing.
Instead of removing from numbers
, try creating a new list appending only the values that meet your conditions.
def purify(numbers):
newNumber = []
for i in numbers:
if i%2 ==0:
newNumber.append(i)
return newNumber
>>>print purify([4,5,5,4])
[4, 4]
Or even simpler:
def purify(numbers):
return [i for i in numbers if i % 2 == 0]
print purify([4,5,5,4])
You almost have it. just add [:] after for i in numbers which will iterate through a copy of the list.
def purify(numbers):
for i in numbers[:]:
if i%2!=0:
numbers.remove(i)
return numbers
print purify([4,5,5,4])
Theres a good explanation below
For more clear picture print the list in each iteration and see what is happening to list and see how the iteration continues.
# i have taken all odd number to try to remove all numbers from list
>>> list = [1,3,5,7]
>>> for num in list:
... if num % 2 != 0:
... list.remove(num)
... print(list)
...
[3, 5, 7]
[3, 7]
You could see that elements moved one position to the left on each remove().
One option I didn’t see mentioned was, ironically filter
:
>>> filter(lambda x: not x % 2, [4,5,5,4])
[4, 4]
Im writing a simple function to take out any odd numbers from a list and return a list of only the even ones.
def purify(numbers):
for i in numbers:
if i%2!=0:
numbers.remove(i)
return numbers
print(purify([4,5,5,4]))
However, the above returns:
[4, 5, 4]
Why doesn’t the second 5 get removed as it also meets the if condition?
Im looking less for a different method to the problem and more to understand why this happens.
When you remove an item, the items that follow get moved one position to the left. This results in the loop skipping some items.
BTW, a more idiomatic way to write that code is
numbers = [num for num in numbers if num % 2 == 0]
>>> listToPurify = [1, 2, 2, 3, 4, 5, 6, 6, 5]
>>> purified = [i for i in listToPurify if i % 2]
>>> purified
[1, 3, 5, 5]
Seems that NPE posted this before me! If you’re confused about list comprehensions, check out here.
If you’d prefer to use a for
loop, you’re going to have to deal with the fact that the length of the list is changing.
Instead of removing from numbers
, try creating a new list appending only the values that meet your conditions.
def purify(numbers):
newNumber = []
for i in numbers:
if i%2 ==0:
newNumber.append(i)
return newNumber
>>>print purify([4,5,5,4])
[4, 4]
Or even simpler:
def purify(numbers):
return [i for i in numbers if i % 2 == 0]
print purify([4,5,5,4])
You almost have it. just add [:] after for i in numbers which will iterate through a copy of the list.
def purify(numbers):
for i in numbers[:]:
if i%2!=0:
numbers.remove(i)
return numbers
print purify([4,5,5,4])
Theres a good explanation below
For more clear picture print the list in each iteration and see what is happening to list and see how the iteration continues.
# i have taken all odd number to try to remove all numbers from list
>>> list = [1,3,5,7]
>>> for num in list:
... if num % 2 != 0:
... list.remove(num)
... print(list)
...
[3, 5, 7]
[3, 7]
You could see that elements moved one position to the left on each remove().
One option I didn’t see mentioned was, ironically filter
:
>>> filter(lambda x: not x % 2, [4,5,5,4])
[4, 4]