SoFunction
Updated on 2025-03-02

Python deletes element cases when traversing lists

tk asked bluerust and scz whether they had encountered this Python pit in the scientific pig farming group.

Example 1:

bas = [ 'ba1', 'ba2', 'ba3', 'ba4', 'ba5' ]
for ba in bas :
    print( ba )
    if ( ( 'ba' ) != -1 ) :
        ( ba )
        print( bas )

print( bas )

That is, dynamically delete elements during the process of traversing the list.

The above code output is as follows:

ba1
['ba2', 'ba3', 'ba4', 'ba5']
ba3                             // ba2 was jumped over['ba2', 'ba4', 'ba5']
ba5                             // ba4 was jumped over['ba2', 'ba4']
['ba2', 'ba4']                  // The list is not deleted

Make some changes to Example 1,

Example 2:

bas = [ 'ba1', 'ba2', 'ba3', 'ba4', 'ba5' ]
for i in range( len( bas ) ) :
    print( i )
    print( bas[i] )
    if ( bas[i].find( 'ba' ) != -1 ) :
        del bas[i]
        print( bas )

print( bas )

The above code output is as follows:

0
ba1
['ba2', 'ba3', 'ba4', 'ba5']
1
ba3
['ba2', 'ba4', 'ba5']
2
ba5
['ba2', 'ba4']
3
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
IndexError: list index out of range
['ba2', 'ba4']

The loop variable i only increments to 3, and then throws an IndexError.

The cause of this pit is that the value of i in the for loop is fixed from the beginning, and in fact, the list is required to remain unchanged in the for loop; the elements are dynamically deleted during the traversal of the list, causing the list to change, while i still stubbornly traverse the list as the original plan, so the elements are missed and the index is crossed.

In this regard, wzhvictor provides 5 solutions.

Method 1, use filter function

bas = [ 'ba1', 'ba2', 'ba3', 'ba4', 'ba5', 'tk' ]
bas = list( filter( lambda ba:( 'ba' ) == -1, bas ) )
print( bas )

Method 2, reconstruct list

bas = [ 'ba1', 'ba2', 'ba3', 'ba4', 'ba5', 'tk' ]
bas = [ba for ba in bas if ( 'ba' ) == -1]
print( bas )

Method 3: traverse the copy of the list and delete the original list

bas = [ 'ba1', 'ba2', 'ba3', 'ba4', 'ba5', 'tk' ]
for ba in bas[:] :
    if ( ( 'ba' ) != -1 ) :
        ( ba )

print( bas )

Method 4

bas = [ 'ba1', 'ba2', 'ba3', 'ba4', 'ba5', 'tk' ]
for ba in bas[:] :
    if ( ( 'ba' ) != -1 ) :
        ( ba )

print( bas )

Method 5, reverse order traversal

bas = [ 'ba1', 'ba2', 'ba3', 'ba4', 'ba5', 'tk' ]
for i in range( len( bas )-1, -1, -1 ) :
    if ( bas[i].find( 'ba' ) != -1 ) :
        del bas[i]

print( bas )

As for example 1 of tk, method 4 is not actually applicable, method 4 is suitable for deleting all specific values ​​from list.

I have never stepped on this pit, I have used methods 2, 3, 4 or their variants. I haven't studied the i value in the for loop as carefully as wzhvictor, but I instinctively don't worry about the objects that are dynamically processed in the loop and I'm too lazy to read Python documents, so I either reconstruct the list or copy the list and then operate it to perfectly avoid pitfalls. I read the article on wzhvictor today. I haven’t used Method 1, I haven’t thought about Method 5, and Method 5 is quite a bit slutty. I’ve seen it for the first time.

There are so many uncertainties on the surface of Python, and it’s no big deal. My experience is that if you can use concise and intuitive deterministic writing, don’t play tricks. Performance optimization is a later story. Next, unit testing does not need to be emphasized.

This is the article about deleting elements when traversing Python lists. For more related contents of Python traversing lists, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!