Python Delete All Entries Of A Value In List
Solution 1:
Never change a list while iterating over it. The results are unpredictable, as you're seeing here. One simple alternative is to construct a new list:
s = [i for i in s if i != 1]
If for some reason you absolutely have to edit the list in place rather than constructing a new one, my off-the-cuff best answer is to traverse it finding the indices that must be deleted, then reverse traverse that list of indices removing them one by one:
indices_to_remove = [i for(i, val) in enumerate(s)ifval== 1]
for i in reversed(indices_to_remove):
del s[i]
Because that removes elements from the end of the list first, the original indices computed remain valid. But I would generally prefer computing the new list unless special circumstances apply.
Solution 2:
Consider this code:
#!/usr/bin/env python
s=[1, 4, 1, 4, 1, 4, 1, 1, 0, 1]
list_size=len(s)
i=0while i!=list_size:
if s[i]==1:
del s[i]
list_size=len(s)
else:
i=i + 1print s
Result:
[4, 4, 4, 0]
For short, your code get some undesirable result because of "size" and "index positions" of your list are changed every times you cut the number 1
off and your code is clearly proved that for each loop
in Python
can not handle a list with a dynamic size.
Solution 3:
You should not change the content of list while iterating over it
But you could iterate over the copy of the list content and change it in your case
Code:
s=[1,4,1,4,1,4,1,1,0,1]
for i in s[:]:
if i ==1: s.remove(i)
print s
Output:
[4, 4, 4, 0]
As @metatoaster stated you could use filter
Code:
s=[1,4,1,4,1,4,1,1,0,1]
s=list(filter(lambda x:x !=1,s))
print s
[4, 4, 4, 0]
You could use filter to remove multiple things example
Code:
s=[1,4,1,4,1,4,1,1,0,1,2,3,5,6,7,8,9,10,20]
remove_element=[1,2,3,5,6,7,8,9]
s=list(filter(lambda x:x not in remove_element,s))
print s
[4, 4, 4, 0, 10, 20]
Solution 4:
This doesn't work because you are modifying the list as it is iterating, and the current pointer moves past one of the 1
you check against. We can illustrate this:
>>>for i in s:...print(s)...if i == 1:... s.remove(i)...
[1_, 4, 1, 4, 1, 4, 1, 1, 0, 1]
[4, 1_, 4, 1, 4, 1, 1, 0, 1]
[4, 4, 1_, 4, 1, 1, 0, 1]
[4, 4, 4, 1_, 1, 0, 1]
[4, 4, 4, 1, 0_, 1]
[4, 4, 4, 1, 0, 1_]
I added _
to the element being compared. Note how there was only 6 passes in total and with one of the 1
s actually skipped over from being ever looked at. That ends up being the element that was removed because list.remove
removes the first occurrence of the element specified, and it is an O(n) operation on its own which gets very expensive once your list gets big - this is O(n) even if the item is in the beginning, as it has to copy every single item from everything after the item one element forward as python list
s are more like C styled arrays than Java linked-lists (if you want to use linked-lists, use collections.deque
). O(n) towards the end because it has to iterate through the entire list to do its own comparison too. Your resulting code can result in a worst case runtime complexity of O(n log n) if you make use of remove
.
See Python's data structure time complexity
Peter's answer already covered the generation of a new list, I am only answering why and how your original code did not work exactly.
Post a Comment for "Python Delete All Entries Of A Value In List"