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的Django框架上部署ORM库的教程
Apr 20 Python
python之Socket网络编程详解
Sep 29 Python
Python实现将Excel转换为json的方法示例
Aug 05 Python
Python进阶之递归函数的用法及其示例
Jan 31 Python
python 读文件,然后转化为矩阵的实例
Apr 23 Python
python获取当前目录路径和上级路径的实例
Apr 26 Python
Pandas 数据处理,数据清洗详解
Jul 10 Python
详解爬虫被封的问题
Apr 23 Python
Django REST Framework之频率限制的使用
Sep 29 Python
利用OpenCV中对图像数据进行64F和8U转换的方式
Jun 03 Python
python3检查字典传入函数键是否齐全的实例
Jun 05 Python
Python3爬虫中识别图形验证码的实例讲解
Jul 30 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中通过smtp发邮件的类,测试通过
2007/01/22 PHP
php中读写文件与读写数据库的效率比较分享
2013/10/19 PHP
PHP文件缓存smarty模板应用实例分析
2016/02/26 PHP
thinkphp3.x中变量的获取和过滤方法详解
2016/05/20 PHP
jquery 可排列的表实现代码
2009/11/13 Javascript
基于Jquery实现的一个图片滚动切换
2012/06/21 Javascript
jQuery实现表头固定效果的实例代码
2013/05/24 Javascript
javascript判断机器是否联网的2种方法
2013/08/09 Javascript
解析JavaScript中delete操作符不能删除的对象
2013/12/03 Javascript
js调用后台、后台调用前台等方法总结
2014/04/17 Javascript
jQuery中大家不太了解的几个方法
2015/03/04 Javascript
javascript实现实时输出当前的时间
2015/04/27 Javascript
详解利用exif.js解决ios手机上传竖拍照片旋转90度问题
2016/11/04 Javascript
浅谈Angular.js中使用$watch监听模型变化
2017/01/10 Javascript
使用Xcache缓存器加速PHP网站的配置方法
2017/04/22 Javascript
详解Vue双向数据绑定原理解析
2017/09/11 Javascript
使用vue实现简单键盘的示例(支持移动端和pc端)
2017/12/25 Javascript
深入理解JavaScript 中的匿名函数((function() {})();)与变量的作用域
2018/08/28 Javascript
python框架中flask知识点总结
2018/08/17 Python
python3+selenium实现qq邮箱登陆并发送邮件功能
2019/01/23 Python
Python 实现递归法解决迷宫问题的示例代码
2020/01/12 Python
解决Jupyter Notebook使用parser.parse_args出现错误问题
2020/04/20 Python
Python模拟登入的N种方式(建议收藏)
2020/05/31 Python
python递归函数用法详解
2020/10/26 Python
美国五金商店:Ace Hardware
2018/03/27 全球购物
办公室文秘自我鉴定
2013/09/21 职场文书
应届生如何写自荐信
2014/01/05 职场文书
上班离岗检讨书
2014/01/27 职场文书
幼儿园教师奖惩制度
2014/02/01 职场文书
《周恩来的四个昼夜》观后思想汇报范文两篇
2014/09/10 职场文书
人身损害赔偿协议书格式
2014/11/01 职场文书
计算机实训报告范文
2014/11/05 职场文书
毕业生评语大全
2015/01/04 职场文书
2015年全国助残日活动方案
2015/05/04 职场文书
2016优秀员工先进事迹材料
2016/02/25 职场文书
vue中利用mqtt服务端实现即时通讯的步骤记录
2021/07/01 Vue.js