- a = [“张三”,”张四”,”张五”,”王二”] 如何删除姓张的
-
a = ["张三", "张四", "张五", "王二"] for i in a: if '张' in i: a.remove(i) print(a)
>>>['张四', '王二']
- 这就有问题了 逻辑是每个元素中只要找到“张”这个字,就删除这个元素
- 但实际这段代码的工作原理是:
- for循环
- 执行第一次循环时,判断张三 有张这个字,执行列表a的删除这个元素
- 列表a删除第一个元素之后,列表后面的元素会向前移
- 即此时列表a= [ "张四", "张五", "王二"] (张三已经被删除了)
执行第二次for循环时
按照下标索引,第一次循环索引下标是0,这一次循环索引下标是1
此时索引下标1对应的元素时“张五”
判断张五元素里面有张字,也执行删除
执行第三次循环
下标2对应的是王二,判断不执行删除
王二是a列表的最后一个元素,for i in a,这个a最后元素已经遍历了,for循环就终止了
另外 下面这段代码 也是同样的原理,问题是会报错
原因是通过len函数,其实就是规定死了for循环的次数
但是实际循环时,因为删除了元素,列表后面的元素产生前移,列表变短
执行最后1次循环 即i=4时,通过[i]索引下标,此时list最后一个元素是list【3】,list【4】自然下标越界报错
list_a = [1, 2, 3, 4, 5]
for i in range(len(list_a)):
if list_a[i] == 2:
list_a.pop(i)
print(list_a)
所以解决办法有两种:
1.使用倒序循环遍历
从下标4,3,2,1,0这样循环,
即从列表最后一个元素往前遍历
这样即使删除元素了,后面的元素前移。而后面前移的元素已经是之前遍历过的,不会影响前面的下标
list_a = [1, 2, 3, 4, 5]
for i in range(len(list_a)-1, -1, -1):
if list_a[i] == 2:
list_a.pop(i)
print(list_a)
2.通过复制一个列表,然后操作这个复制的列表,读取这个复制列表的索引或者元素信息,然后再根据这个信息反过来去操作原列表
复制后的列表遍历时,只读取,不操作,自然数据不会改变
下面代码中的num_list[:] 相当于切片操作,但是没有切任何数据,返回跟原列表一样的数据,但是不是原列表,切片的返回值是一个新列表,而这个新列表保留了原列表所有的元素,即相当于复制
list_a = [1, 2, 3, 4, 5]
for i list_a[:]:
if i == 2:
list_a.remove(i)
print(list_a)