x = [1,2,3,4,5,6,7,8,9]
for i in range(len(x)):
if i > 5:
x.remove(i)
print (x)
When I execute this code, I get x = [1,2,3,4,5,9], when I was attempting to take out everything above 5. What would make this accurate?
4 Answers 4
The idiomatic solution in Python for this kind of problems is to use a list comprehension. Try this:
[e for e in x if e <= 5]
=> [1, 2, 3, 4, 5]
Comments
Your indices range from 0 through to 8:
>>> x = [1,2,3,4,5,6,7,8,9]
>>> list(range(len(x)))
[0, 1, 2, 3, 4, 5, 6, 7, 8]
but list.remove() removes items by value.
You'd have to do:
for i in range(len(x)):
if x[i] > 5:
x.remove(i)
instead, but that'd only remove the first such value. Moreover, this will end up skipping indices, eventually ending with a IndexError.
Because you are removing items, the values following the one you removed all shift up one step. The value 7 is now at index 5 (it was at 6):
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x.index(7)
6
>>> x.remove(6)
>>> x.index(7)
5
>>> x
[1, 2, 3, 4, 5, 7, 8, 9]
but the loop still keeps on counting. The loop goes from i = 5 to i = 6, where we now have the number 8, having missed the number 7. And the list is now 1 element shorter but the range() was already calculated at the start of the loop. We'll get an IndexError when we run out of list but not out of indices.
When removing items from a list, it is far easier to use a list comprehension to filter instead, in a list comprehension:
x = [i for i in x if i <= 5]
This keeps all elements that are 5 or smaller, and because it builds a new list, you don't run into the resizing existing list problem.
1 Comment
Given this list:
>>> x=[1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1]
If you just want the list elements until a condition is met, use itertools.takewhile:
>>> from itertools import takewhile
>>> list(takewhile(lambda e: e<=5, x))
[1, 2, 3, 4, 5]
To filter the elements where each element meets a condition, use filter:
>>> list(filter(lambda e: e<=5, x))
[1, 2, 3, 4, 5, 5, 4, 3, 2, 1]
Or, use a list comprehension as Óscar López or Martijn Pieters have suggested.
Comments
In Range you ve to remember about Zero indexing.
range(N) -> start from Zero to N-1
range(4) returns [0, 1, 2, 3]
or
range(start, stop[, step]) -> list of integers
So, you can fixed your snippet by changing the range:
>>> x = [1,2,3,4,5,6,7,8,9]
>>> for i in range(1, len(x) + 1):
... if i > 5:
... x.remove(i)
...
>>> print x
[1, 2, 3, 4, 5]
>>>
But this case was lucky because your list was in sequence else it won't give you the right answer.
Here is just another options:
>>> x = [9,2,3,4,1,5,6]
>>> y = sorted(x)
>>> y[0:x.index(5)]
[1, 2, 3, 4, 5]
>>>
x.remove()does not remove the index but the value.x.remove(6)removes the value at index 7. You are mixing indices and values here.numpyarrays. Not everybody uses numpy.