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中使用select模块实现非阻塞的IO
Feb 03 Python
基于python实现的抓取腾讯视频所有电影的爬虫
Apr 22 Python
Python编程实现删除VC临时文件及Debug目录的方法
Mar 22 Python
python使用Plotly绘图工具绘制散点图、线形图
Apr 02 Python
python 标准差计算的实现(std)
Jul 29 Python
Python使用grequests(gevent+requests)并发发送请求过程解析
Sep 25 Python
Python with语句和过程抽取思想
Dec 23 Python
Django REST framwork的权限验证实例
Apr 02 Python
Python unittest单元测试框架实现参数化
Apr 29 Python
python tkinter的消息框模块(messagebox,simpledialog)
Nov 07 Python
Python爬虫Scrapy框架CrawlSpider原理及使用案例
Nov 20 Python
pd.DataFrame中的几种索引变换的实现
Jun 16 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 批量删除数据的方法分析
2009/10/30 PHP
php excel类 phpExcel使用方法介绍
2010/08/21 PHP
php方法调用模式与函数调用模式简例
2011/09/20 PHP
JavaScript入门学习书籍推荐
2008/06/12 Javascript
Javascript 判断函数类型完美解决方案
2009/09/02 Javascript
js 操作符实例代码
2009/10/24 Javascript
JQuery toggle使用分析
2009/11/16 Javascript
Javascript attachEvent传递参数的办法
2009/12/14 Javascript
JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
2010/01/12 Javascript
javascript编码的几个方法详细介绍
2013/01/06 Javascript
滚动图片效果 jquery实现回旋滚动效果
2013/01/08 Javascript
jquery获取radio值(单选组radio)
2014/10/16 Javascript
详解Vue学习笔记进阶篇之列表过渡及其他
2017/07/17 Javascript
在Vue.js中使用Mixins的方法
2017/09/12 Javascript
浅谈Vue网络请求之interceptors实际应用
2018/02/28 Javascript
JavaScript调用模式与this关键字绑定的关系
2018/04/21 Javascript
vue-router传参用法详解
2019/01/19 Javascript
javascript设计模式 ? 建造者模式原理与应用实例分析
2020/04/10 Javascript
vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件
2021/02/20 Vue.js
[01:20]DOTA2 齐天大圣至宝动态展示
2016/12/13 DOTA
Python去除字符串两端空格的方法
2015/05/21 Python
python模拟登陆,用session维持回话的实例
2018/12/27 Python
pyqt5中QThread在使用时出现重复emit的实例
2019/06/21 Python
dpn网络的pytorch实现方式
2020/01/14 Python
解决python -m pip install --upgrade pip 升级不成功问题
2020/03/05 Python
Tensorflow加载Vgg预训练模型操作
2020/05/26 Python
详解解决jupyter不能使用pytorch的问题
2021/02/18 Python
CSS3中的transform属性进行2D和3D变换的基本用法
2016/05/12 HTML / CSS
软件测试英文面试题
2012/10/14 面试题
秘书岗位职责
2013/11/18 职场文书
计算机专业推荐信范文
2013/11/20 职场文书
专科应届生求职信
2013/11/24 职场文书
激情洋溢的毕业生就业求职信
2014/03/15 职场文书
保健品市场营销方案
2014/03/31 职场文书
驻村工作简报
2015/07/20 职场文书
[有人@你]你有一封绿色倡议书,请查收!
2019/07/18 职场文书