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中的list列表数据结构用法
Mar 12 Python
谈谈如何手动释放Python的内存
Dec 17 Python
HTML中使用python屏蔽一些基本功能的方法
Jul 07 Python
Tensorflow实现卷积神经网络的详细代码
May 24 Python
NLTK 3.2.4 环境搭建教程
Sep 19 Python
对pandas的层次索引与取值的新方法详解
Nov 06 Python
PyTorch 1.0 正式版已经发布了
Dec 13 Python
Python 分享10个PyCharm技巧
Jul 13 Python
windows、linux下打包Python3程序详细方法
Mar 17 Python
Python使用Pyqt5实现简易浏览器(最新版本测试过)
Apr 27 Python
如何在pycharm中安装第三方包
Oct 27 Python
Ubuntu20下的Django安装的方法步骤
Jan 24 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
动态新闻发布的实现及其技巧
2006/10/09 PHP
apache php模块整合操作指南
2012/11/16 PHP
深入解析php中的foreach函数
2013/08/31 PHP
php实现的ping端口函数实例
2014/11/12 PHP
CodeIgniter辅助之第三方类库third_party用法分析
2016/01/20 PHP
JavaScript编程开发中的五个实用小技巧
2010/07/22 Javascript
JS限制上传图片大小不使用控件在本地实现
2012/12/19 Javascript
通过location.replace禁止浏览器后退防止重复提交
2014/09/04 Javascript
JS获取鼠标坐标位置实例分析
2016/01/20 Javascript
jQuery循环遍历子节点并获取值的方法
2016/04/14 Javascript
浅谈JQ中mouseover和mouseenter的区别
2016/09/13 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单
2016/11/25 Javascript
bootstrap轮播图示例代码分享
2017/05/17 Javascript
js实现网页同时进行多个倒计时功能
2019/02/25 Javascript
Node.js动手撸一个静态资源服务器的方法
2019/03/09 Javascript
微信小程序移动拖拽视图-movable-view实例详解
2019/08/17 Javascript
Vue退出登录时清空缓存的实现
2019/11/12 Javascript
vue组件添加事件@click.native操作
2020/10/30 Javascript
[50:54]完美世界DOTA2联赛 GXR vs IO 第三场 11.07
2020/11/10 DOTA
Python 25行代码实现的RSA算法详解
2018/04/10 Python
bluepy 一款python封装的BLE利器简单介绍
2019/06/25 Python
详解Python3 pandas.merge用法
2019/09/05 Python
Django CSRF认证的几种解决方案
2020/03/03 Python
使用python执行shell脚本 并动态传参 及subprocess的使用详解
2020/03/06 Python
使用python批量修改XML文件中图像的depth值
2020/07/22 Python
法国时尚童装网站:Melijoe
2016/08/10 全球购物
梅西百货澳大利亚:Macy’s Australia
2017/07/26 全球购物
俄罗斯化妆品和香水网上商店:Iledebeaute
2019/01/03 全球购物
神路信息Java面试题目
2013/03/31 面试题
化工工艺专业求职信
2013/09/22 职场文书
旅游项目开发策划书
2014/01/18 职场文书
2014年端午节活动方案
2014/03/11 职场文书
一份没有按时交货失信于客户的检讨书
2014/09/19 职场文书
2015年上半年信访工作总结
2015/03/30 职场文书
Win11怎么启动任务管理器?Win11启动任务管理器的几种方法
2021/11/23 数码科技
Tomcat执行startup.bat出现闪退的原因及解决办法
2022/04/20 Servers