Python中list循环遍历删除数据的正确方法


Posted in Python onSeptember 02, 2019

前言

初学Python,遇到过这样的问题,在遍历list的时候,删除符合条件的数据,可是总是报异常,代码如下:

num_list = [1, 2, 3, 4, 5]
print(num_list)

for i in range(len(num_list)):
 if num_list[i] == 2:
  num_list.pop(i)
 else:
  print(num_list[i])

print(num_list)

会报异常:IndexError: list index out of range

原因是在删除list中的元素后,list的实际长度变小了,但是循环次数没有减少,依然按照原来list的长度进行遍历,所以会造成索引溢出。

于是我修改了代码如下:

num_list = [1, 2, 3, 4, 5]
print(num_list)

for i in range(len(num_list)):
 if i >= len(num_list):
  break

 if num_list[i] == 2:
  num_list.pop(i)
 else:
  print(num_list[i])

print(num_list)

这回不会报异常了,但是打印结果如下:

[1, 2, 3, 4, 5]
1
4
5
[1, 3, 4, 5]
[Finished in 0.441s]

虽然最后,list中的元素[2]确实被删除掉了,但是,在循环中的打印结果不对,少打印了[3]。

思考了下,知道了原因,当符合条件,删除元素[2]之后,后面的元素全部往前移,于是[3, 4, 5]向前移动,那么元素[3]的索引,就变成了之前[2]的索引(现在[3]的下标索引变为1了),后面的元素以此类推。可是,下一次for循环的时候,是从下标索引2开始的,于是,取出了元素[4],就把[3]漏掉了。

把代码修改成如下,结果一样,丝毫没有改观:

num_list = [1, 2, 3, 4, 5]
print(num_list)

for item in num_list:
 if item == 2:
  num_list.remove(item)
 else:
  print(item)

print(num_list)

既然知道了问题的根本原因所在,想要找到正确的方法,也并不难,于是我写了如下的代码:

num_list = [1, 2, 3, 4, 5]
print(num_list)

i = 0
while i < len(num_list):
 if num_list[i] == 2:
  num_list.pop(i)
  i -= 1
 else:
  print(num_list[i])

 i += 1

print(num_list)

执行结果,完全正确:

[1, 2, 3, 4, 5]
1
3
4
5
[1, 3, 4, 5]
[Finished in 0.536s]

我的做法是,既然用for循环不行,那就换个思路,用while循环来搞定。每次while循环的时候,都会去检查list的长度(i < len(num_list)),这样,就避免了索引溢出,然后,在符合条件,删除元素[2]之后,手动把当前下标索引-1,以使下一次循环的时候,通过-1后的下标索引取出来的元素是[3],而不是略过[3]。

当然,这还不是最优解,所以,我搜索到了通用的解决方案:1、倒序循环遍历;2、遍历拷贝的list,操作原始的list。

1、倒序循环:

num_list = [1, 2, 3, 4, 5]
print(num_list)

for i in range(len(num_list)-1, -1, -1):
 if num_list[i] == 2:
  num_list.pop(i)
 else:
  print(num_list[i])

print(num_list)

执行结果完全正确。那么,为何正序循环时删除就有问题,而倒序循环时删除就ok?额。。。。。。言语难表,还是画个丑图出来吧。

1)正序循环时删除:

Python中list循环遍历删除数据的正确方法

删除元素[2]之后,下一次循环的下标索引为2,但此时,里面存放的是[4],于是就把[3]给漏了。

2)倒序循环时删除

Python中list循环遍历删除数据的正确方法

删除元素[2]后,[3, 4, 5]往前挤,但是没关系,因为下一次循环的下标索引为0,里面存放的是[1],所以正是我们所期望的正确的元素值。

2、遍历拷贝的list,操作原始的list

num_list = [1, 2, 3, 4, 5]
print(num_list)

for item in num_list[:]:
 if item == 2:
  num_list.remove(item)
 else:
  print(item)

print(num_list)

原始的list是num_list,那么其实,num_list[:]是对原始的num_list的一个拷贝,是一个新的list,所以,我们遍历新的list,而删除原始的list中的元素,则既不会引起索引溢出,最后又能够得到想要的最终结果。此方法的缺点可能是,对于过大的list,拷贝后可能很占内存。那么对于这种情况,可以用倒序遍历的方法来实现。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
可用于监控 mysql Master Slave 状态的python代码
Feb 10 Python
python控制台英汉汉英电子词典
Apr 23 Python
python使用标准库根据进程名如何获取进程的pid详解
Oct 31 Python
详解如何利用Cython为Python代码加速
Jan 27 Python
Python面向对象之静态属性、类方法与静态方法分析
Aug 24 Python
python地震数据可视化详解
Jun 18 Python
解决Python设置函数调用超时,进程卡住的问题
Aug 08 Python
Python中字典与恒等运算符的用法分析
Aug 22 Python
浅析python内置模块collections
Nov 15 Python
Python 实现进度条的六种方式
Jan 06 Python
python链表类中获取元素实例方法
Feb 23 Python
python之django路由和视图案例教程
Jul 26 Python
python中matplotlib条件背景颜色的实现
Sep 02 #Python
Python3批量移动指定文件到指定文件夹方法示例
Sep 02 #Python
Python流程控制 if else实现解析
Sep 02 #Python
Python 变量的创建过程详解
Sep 02 #Python
python脚本之一键移动自定格式文件方法实例
Sep 02 #Python
Python中zip()函数的简单用法举例
Sep 02 #Python
Python在OpenCV里实现极坐标变换功能
Sep 02 #Python
You might like
web方式ftp
2006/10/09 PHP
CodeIgniter框架数据库事务处理的设计缺陷和解决方案
2014/07/25 PHP
js Array操作的最简短最容易理解方法
2013/12/09 Javascript
jquery.post用法示例代码
2014/01/03 Javascript
JavaScript AJAX之惰性载入函数
2014/08/27 Javascript
jQuery随手笔记之常用的jQuery操作DOM事件
2015/11/29 Javascript
jQuery中inArray方法注意事项分析
2016/01/25 Javascript
JQuery 进入页面默认给已赋值的复选框打钩
2017/03/23 jQuery
JS设计模式之单例模式(一)
2017/09/29 Javascript
vue2.0 + element UI 中 el-table 数据导出Excel的方法
2018/03/02 Javascript
详解.vue文件解析的实现
2018/06/11 Javascript
详解将微信小程序接口Promise化并使用async函数
2019/08/05 Javascript
解决vux 中popup 组件Mask 遮罩在最上层的问题
2020/11/03 Javascript
Python构建XML树结构的方法示例
2017/06/30 Python
Zookeeper接口kazoo实例解析
2018/01/22 Python
Python Xml文件添加字节属性的方法
2018/03/31 Python
Python生成器定义与简单用法实例分析
2018/04/30 Python
Python实现的knn算法示例
2018/06/14 Python
5分钟 Pipenv 上手指南
2018/12/20 Python
对Python3 goto 语句的使用方法详解
2019/02/16 Python
pyqt5利用pyqtDesigner实现登录界面
2019/03/28 Python
Python+PyQt5实现美剧爬虫可视工具的方法
2019/04/25 Python
Windows10下 python3.7 安装 facenet的教程
2019/09/10 Python
修改Pandas的行或列的名字(重命名)
2019/12/18 Python
1688平价精选商城:阿里集团旗下,工厂出厂价格直销
2017/04/24 全球购物
斯洛伐克电子产品购物网站:DATART
2020/04/05 全球购物
广州地球村科技数据库题目
2016/04/25 面试题
汽车运用工程毕业生自荐信
2013/10/29 职场文书
品质主管岗位职责
2014/03/16 职场文书
保护环境的标语
2014/06/09 职场文书
个人求职自荐信范文
2014/06/20 职场文书
就业协议书范本
2014/10/08 职场文书
先进集体申报材料
2014/12/25 职场文书
民间借贷纠纷案件代理词
2015/05/26 职场文书
食堂卫生管理制度
2015/08/04 职场文书
话题作文之呼唤
2019/12/18 职场文书