Why is list.remove only removing every second item?

后端 未结 6 1604
执念已碎
执念已碎 2021-01-23 04:59

In my Python 2.7.2 IDLE interpreter:

>>> mylist = [1, 2, 3, 4, 5]
>>> for item in mylist:
        mylist.remove(item)

>>> mylist
[2,          


        
相关标签:
6条回答
  • 2021-01-23 05:26

    It's because when you iterate over a list, python keeps track of the index in the list. Consider the following code instead:

    for i in range(len(mylist)):
        if i >= len(mylist):
           break
        item = mylist[i]
        mylist.remove(item)
    

    If we track this (which is essentially what python is doing in your code), then we see that when we remove an item in the list, the number to the right shifts one position to the left to fill the void left when we removed the item. The right item is now at index i and so it will never actually get seen in the iteration because the next thing that happens is we increment i for the next iteration of the for loop.


    Now for something a little clever. If instead we iterate over the list backward, we'll clear out the list:

    for item in reversed(mylist):
        mylist.remove(item)
    

    The reason here is that we're taking an item off the end of the list at each iteration of the for loop. Since we're always taking items off the end, nothing needs to shift (assuming uniqueness in the list -- If the list isn't unique, the result is the same, but the argument gets a bit more complicated).

    Of course, If you're looking to remove all the items from a list, you can do that really easily:

    del mylist[:]
    

    or even with slice assignment:

    mylist[:] = []
    

    (I mention the latter because it can be useful to replace segments of a list with other items which don't even need to be the same length).

    0 讨论(0)
  • 2021-01-23 05:29
    >>> mylist = [1, 2, 3, 4, 5]
    
    >>> for item in mylist:
            mylist.remove(item)
    

    in this loop : 1st time it will take 0th element (1) as an item and remove it from mylist.so after that mylist will be [2,3,4,5] but the pointer will be in the 1th element of the new mylist ([2,3,4,5]) that is 3. and it will remove 3.so 2 will not be remove from the list.

    thats why after the full operation [2,4] will be left.

    using for loop:-
    >>>for i in range(len(mylist)):
           mylist.remove(mylist[0])
           i-=1
    
    >>>mylist
    []
    

    you can do this using while loop:

    >>>mylist = [1, 2, 3, 4, 5]
    >>>while (len(mylist)>0):
           mylist.remove(mylist[0])
           print mylist
    
    0 讨论(0)
  • 2021-01-23 05:36

    You are modifying your list while you are looping through it, which is very bad practice.

    0 讨论(0)
  • 2021-01-23 05:40

    Use a deep copy of mylist

    mylist = [1, 2, 3, 4, 5]
    
    l = [k for k in mylist] # deep copy
    
    for i in range(len(mylist)):
        mylist.remove(l[i])
        print 
    
    print mylist
    
    0 讨论(0)
  • 2021-01-23 05:43

    Problem is that you are altering the list while iterating on it. Use a list comprehension instead:

    mylist = [1, 2, 3, 4, 5]
    mylist = [x for x in mylist if condition(x)]
    
    0 讨论(0)
  • 2021-01-23 05:44

    That's because you're modifying the list while iterating over it, iterate over a shallow copy instead:

    >>> mylist = [1, 2, 3, 4, 5]
    >>> for item in mylist[:]:      #use mylist[:] or list(mylist)
                mylist.remove(item)
    ...     
    >>> mylist
    []
    
    0 讨论(0)
提交回复
热议问题