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 相关文章推荐
pygame学习笔记(6):完成一个简单的游戏
Apr 15 Python
Python ftp上传文件
Feb 13 Python
Python中使用插入排序算法的简单分析与代码示例
May 04 Python
Pyhton中单行和多行注释的使用方法及规范
Oct 11 Python
对pandas的算术运算和数据对齐实例详解
Dec 22 Python
python3使用QQ邮箱发送邮件
May 20 Python
Python中的asyncio代码详解
Jun 10 Python
Python利用scapy实现ARP欺骗的方法
Jul 23 Python
Python空间数据处理之GDAL读写遥感图像
Aug 01 Python
python闭包、深浅拷贝、垃圾回收、with语句知识点汇总
Mar 11 Python
Python基于pandas绘制散点图矩阵代码实例
Jun 04 Python
Python web框架(django,flask)实现mysql数据库读写分离的示例
Nov 18 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中的时间显示
2007/01/18 PHP
PHP小技巧之JS和CSS优化工具Minify的使用方法
2014/05/19 PHP
PHP实现获取ip地址的5种方法,以及插入用户登录日志操作示例
2019/02/28 PHP
redis+php实现微博(一)注册与登录功能详解
2019/09/23 PHP
Alliance vs AM BO3 第二场2.13
2021/03/10 DOTA
javascript编程起步(第三课)
2007/02/27 Javascript
ext实现完整的登录代码
2008/08/08 Javascript
csdn 批量接受好友邀请
2009/02/19 Javascript
javascript:文字不间断向左移动的实例代码
2013/08/08 Javascript
JQuery中serialize()、serializeArray()和param()方法示例介绍
2014/07/31 Javascript
javascript+html5实现仿flash滚动播放图片的方法
2015/04/27 Javascript
jQuery中closest和parents的区别分析
2015/05/07 Javascript
jquery对象访问是什么及使用方法介绍
2016/05/03 Javascript
深入理解javascript函数参数与闭包
2016/12/12 Javascript
JS与SQL方式随机生成高强度密码示例
2018/12/29 Javascript
Nest.js环境变量配置与序列化详解
2021/02/21 Javascript
[58:35]OG vs EG 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.22
2019/09/05 DOTA
python strip()函数 介绍
2013/05/24 Python
利用Anaconda简单安装scrapy框架的方法
2018/06/13 Python
Python字典常见操作实例小结【定义、添加、删除、遍历】
2019/10/25 Python
localStorage、sessionStorage使用总结
2017/11/17 HTML / CSS
加拿大折扣、优惠券和交易网站:WagJag
2018/02/07 全球购物
Groupon西班牙官方网站:在线优惠券和交易,节省高达70%
2021/03/13 全球购物
对象的序列化(serialization)类是面向流的,应如何将对象写入到随机存取文件中
2015/06/22 面试题
求职推荐信
2013/10/28 职场文书
买房子个人收入证明
2014/01/16 职场文书
信息技术专业大学生职业生涯规划书
2014/01/24 职场文书
《夏夜多美》教学反思
2014/02/17 职场文书
车间主任岗位职责范本
2015/04/08 职场文书
2015年人事专员工作总结
2015/04/29 职场文书
教师节领导致辞
2015/07/29 职场文书
歌咏比赛口号大全
2015/12/25 职场文书
《山中访友》教学反思
2016/02/24 职场文书
利用Java设置Word文本框中的文字旋转方向的实现方法
2021/06/28 Java/Android
mysql下的max_allowed_packet参数设置详解
2022/02/12 MySQL
深入理解 Golang 的字符串
2022/05/04 Golang