如何高效删除List元素是一个值得思考的命题,如果单单考虑时间复杂度,可能会带来额外的空间复杂度。
对Pthon而言 迭代中删除List元素是一个不那么安全的行为,下面记录了一些遇到的坑(拓展性踩坑,防错):
- 使用del
del是使用下标进行删除
请看代码:
a = [0, 1, 2, 3, 4, 5, 6]
# 使用del
for i in range(len(a)):
try:
if a[i] == 3 or a[i] == 5:
del a[i]
else:
print(i)
except:
print('out of : ', i)
break
print(a)
此代码会报错:
0
1
2
out of : 5
[0, 1, 2, 5, 6]
报错的原因是删除第一个之后,下标5时会出现越界。
增加几行代码,可以看到具体原因:
a = [0, 1, 2, 3, 4, 5, 6]
# 使用del
for i in range(len(a)):
try:
if a[i] == 3 or a[i] == 5:
print('i={}, a[{}] = {} ,org a={}, '.format(
i, i, a[i], a), end='')
del a[i]
print('deleted a ={}'.format(a))
else:
print(i)
except:
print('out of : ', i)
break
print(a)
输出:
0
1
2
i=3, a[3] = 3 ,org a=[0, 1, 2, 3, 4, 5, 6], deleted a =[0, 1, 2, 4, 5, 6]
i=4, a[4] = 5 ,org a=[0, 1, 2, 4, 5, 6], deleted a =[0, 1, 2, 4, 6]
out of : 5
[0, 1, 2, 4, 6]
*可以使用while来控制变量解决这个问题
-
使用remove:
remove是根据值来删除为了简单验证,我们首先假定该list没有重复的值,并且换一种方式,挑战迭代中删除元素:
a = [0, 1, 2, 3, 4, 5, 6]
# 使用del
for i in a:
try:
if i == 3 or i == 6:
print('i={},,org a={}, '.format(
i, a), end='')
#del a[i]
a.remove(i)
print('deleted a ={}'.format(a))
else:
print(i)
except:
print('error : ', i)
break
该代码未报错:
0
1
2
i=3,,org a=[0, 1, 2, 3, 4, 5, 6], deleted a =[0, 1, 2, 4, 5, 6]
5
i=6,,org a=[0, 1, 2, 4, 5, 6], deleted a =[0, 1, 2, 4, 5]
[0, 1, 2, 4, 5]
细心的朋友就会发现,这样做会造成bug,4并没有打印出来
将两个值更改以下:
a = [0, 1, 2, 3, 4, 5, 6]
# 使用del
for i in a:
try:
if i == 4 or i == 3:
print('i={},,org a={}, '.format(
i, a), end='')
#del a[i]
a.remove(i)
print('deleted a ={}'.format(a))
else:
print(i)
except:
print('error : ', i)
break
print(a)
得到:
0
1
2
i=3,,org a=[0, 1, 2, 3, 4, 5, 6], deleted a =[0, 1, 2, 4, 5, 6]
5
6
[0, 1, 2, 4, 5, 6]
迭代机制造成了4根本没被遍历到
list设计之初就不适合增加删除中间元素,有类似的需求根据具体情况具体分析选择使用list还是链表。