目录
前言
在工作项目中用到了列表删除的处理,故总结了python列表删除多个下标时的不同方法以及笔者最后用到的最优解。
一、题目
对比不同的解法,找出最佳的解决方案
已知一个列表[1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]
删除列表所在的索引[0,5,14,17]
被删掉的元素有1,6,6,9
预期结果:[2,3,4,5,7,8,9,1,2,3,4,5,7,8]
二、解决方法
用哪几种算法可以做到?
1、使用del函数
首先想到的是del 删除指定下标
但是,直接抛异常,下标超出列表范围了
调试看看,发生了什么,为什么会下标越界?
调试时,可以看到,在每删除一个元素后,都会形成一个新的列表,这时删掉的元素就错了一位,第2次删除下标为5的值,应该删的新列表里下标为4的值,但这时仍删的下标为5的值,删到第4个元素时,此时列表长度只有15,当然找不到下标为17的元素。
删除指定下标,还有pop方法,如果做遍历,形成新的列表,和上面的del方法一样,都不符合我们的预期 。
上面用del方法删除时,for循环一次,新列表在变,这时要删除的下标索引跟着去变,试试这种方法,可以看到结果符合我们的预期
2、使用remove函数
先找到指定元素,再去删除指定元素,这种方法是否可行,试一下
[2, 3, 4, 5, 7, 8, 1, 2, 3, 4, 5, 7, 8, 9],我们发现,9这个元素,找到后删除的是第一个,不是我们预期的索引为17的9
debug,调试看下
3、使用enumerate函数
博主整理了下python进阶的知识,可参考Python进阶(一)中对enumerate函数的介绍。
使用列表生成器,[x for x,y in enumerate(all_list) if x not in delete_index_list],这行代码的意思是遍历得到列表的下标y和值x,如果下标在需要删除的下标列表里,则不取出,反之,则取出值,最后所有值放到一个列表里。
符合我们的预期,看来这种方法可行。
根据上面删除动态的下标思路,还可以用到 for i,x in enumerate()这个函数
具体代码:
三、寻找最优解
使用不同的算法,找出耗时最少的算法
试下来,有两种代码可以符合我们的预期,但毕竟在实际工作中,处理数据时,会有非常大的数据量,现在用大的数据来完成删除操作,看哪种方法的耗时更少些。
原列表长度时219708,要删除149996个元素
先用[y for x, y in enumerate(list_all) if x not in remove_index_all]
在等待时,发现有提示,可以看到,先做遍历,然后再做判断,如果不是要删掉的,则添加元素至新的列表,这样的算法,实际很麻烦,运行结果同上
再用for i,x in enumerate(),依次删除
可以看到用遍历一次,删一次,这种方法耗时更少
四、结论
删除列表的多个下标时,推荐使用以下的方法:
all_list = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]
delete_index_list = [0,5,14,17]
for change_index,delete_index in enumerate(delete_index_list):
delete_index -= change_index
del all_list[delete_index]
print(all_list)