Python遍历列表时删除元素

admin 2022年9月4日15:32:19安全开发评论0 views2094字阅读6分58秒阅读模式
作者: wzhvictor
创建: 2016-10-19

tk在科学养猪群里问bluerust、scz是否碰上过这个Python坑,示例1

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

print( bas )

即遍历list的过程中动态删除元素。上述代码输出如下

ba1
['ba2''ba3''ba4''ba5']
ba3                             // ba2被跳过去了
['ba2''ba4''ba5']
ba5                             // ba4被跳过去了
['ba2''ba4']
['ba2''ba4']                  // 列表未删干净

然后tk搜了个链接

https://segmentfault.com/a/1190000007214571

这篇讲得清楚,建议直接看原文,作者是wzhvictor。

对示例1做点改动,示例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 )

上述代码输出如下

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

循环变量i只递增到3,进而抛出IndexError。

该坑的起因是,for循环中i的取值从最开始就固定了,实际上要求list在for循环中保持不变;遍历list的过程中动态删除元素,导致list发生变化,而i仍固执地按原计划递增遍历list,于是漏删元素、索引越界。

对此,wzhvictor给了5种解决方案。

方式1,利用filter函数

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

方法2,重新构造list

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

方法3,遍历list的拷贝,对原始list进行删除操作

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

print( bas )

方法4

bas = [ 'ba''ba''ba''ba''ba''tk' ]
while 'ba' in bas :
    bas.remove( 'ba' )

print( bas )

方法5,倒序遍历

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 )

就tk的示例1而言,方法4其实不适用,方法4适合从list中删除所有特定值。

这个坑我没踩过,用过方法2、3、4或者它们的变种。没像wzhvictor那样细究过for循环中i取值从最开始就固定,但我本能地对循环中动态处理的对象不放心,又懒得看Python文档,所以要么重新构造list,要么复制list再操作,完美避坑。今日看了wzhvictor的文章,方法1没用过,方法5没想过,方法5比较骚包,我第一次见。

Python表面上的不确定性真多,也没啥大不了,我的经验是,能用简明直观确定性的写法,就不要骚包玩花活,性能优化是后话。再就是,单元测试,无需再多强调。

原文始发于微信公众号(青衣十三楼飞花堂):Python遍历列表时删除元素

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年9月4日15:32:19
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  Python遍历列表时删除元素 http://cn-sec.com/archives/1275488.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: