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 相关文章推荐
Python 3.x 新特性及10大变化
Jun 12 Python
python+opencv识别图片中的圆形
Mar 25 Python
Python 数据处理库 pandas 入门教程基本操作
Apr 19 Python
Python for循环中的陷阱详解
Jul 13 Python
python3 中的字符串(单引号、双引号、三引号)以及字符串与数字的运算
Jul 18 Python
PyQt5 界面显示无响应的实现
Mar 26 Python
对python中arange()和linspace()的区别说明
May 03 Python
Python基于BeautifulSoup爬取京东商品信息
Jun 01 Python
Keras—embedding嵌入层的用法详解
Jun 10 Python
Python实现迪杰斯特拉算法并生成最短路径的示例代码
Dec 01 Python
基于Pytorch版yolov5的滑块验证码破解思路详解
Feb 25 Python
Python使用psutil库对系统数据进行采集监控的方法
Aug 23 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
php INI配置文件的解析实现分析
2011/01/04 PHP
php 面向对象的一个例子
2011/04/12 PHP
php cookies中删除的一般赋值方法
2011/05/07 PHP
php+js实现图片的上传、裁剪、预览、提交示例
2013/08/27 PHP
CodeIgniter框架数据库事务处理的设计缺陷和解决方案
2014/07/25 PHP
php 三元运算符实例详细介绍
2016/12/15 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
2019/12/20 PHP
Javascript常用运算符(Operators)-javascript基础教程
2007/12/14 Javascript
javaScript parseInt字符转化为数字函数使用小结
2009/11/05 Javascript
js继承的实现代码
2010/08/05 Javascript
基于jQuery的图片大小自动适应实现代码
2010/11/17 Javascript
JS拖动技术 关于setCapture使用
2010/12/09 Javascript
JQuery中操作Css样式的方法
2014/02/12 Javascript
webpack+vue.js实现组件化详解
2016/10/12 Javascript
Bootstrap布局之栅格系统学习笔记
2017/05/04 Javascript
使用Browserify来实现CommonJS的浏览器加载方法
2017/05/14 Javascript
详解js类型判断
2018/05/22 Javascript
AngularJS 多指令Scope问题的解决
2018/10/25 Javascript
如何封装Vue Element的table表格组件
2021/02/06 Vue.js
[03:00]DOTA2-DPC中国联赛1月18日Recap集锦
2021/03/11 DOTA
python解析xml文件操作实例
2014/10/05 Python
python实现二分查找算法
2017/09/21 Python
Python tornado队列示例-一个并发web爬虫代码分享
2018/01/09 Python
Python温度转换实例分析
2018/01/17 Python
pandas对指定列进行填充的方法
2018/04/11 Python
python实现指定ip端口扫描方式
2019/12/17 Python
Python如何用filter函数筛选数据
2020/03/05 Python
Expected conditions模块使用方法汇总代码解析
2020/08/13 Python
python爬虫工具例举说明
2020/11/30 Python
CSS3实现大小不一的粒子旋转加载动画
2016/04/21 HTML / CSS
广州盈通面试题
2015/12/05 面试题
清洁工个人总结
2015/03/04 职场文书
自我检讨书怎么写
2015/05/07 职场文书
幽默导游词应该怎么写?
2019/08/26 职场文书
Django migrate报错的解决方案
2021/05/20 Python
2007年老电脑安装win11会怎么样? 网友实测win11在老电脑运行良好
2021/11/21 数码科技