Python的list循环遍历中,删除数据的正确方法

在遍历list,删除符合条件的数据时,总是报异常,代码如下:

 1 num_list = [1, 2, 3, 4, 5]
 2 print(num_list)
 3
 4 for i in range(len(num_list)):
 5     if num_list[i] == 2:
 6         num_list.pop(i)
 7     else:
 8         print(num_list[i])
 9
10 print(num_list)

会报异常:IndexError: list index out of range

原因是在删除list中的元素后,list的实际长度变小了,但是循环次数没有减少,依然按照原来list的长度进行遍历,所以会造成索引溢出。

修改代码如下:

 1 num_list = [1, 2, 3, 4, 5]
 2 print(num_list)
 3
 4 for i in range(len(num_list)):
 5     if i >= len(num_list):
 6         break
 7
 8     if num_list[i] == 2:
 9         num_list.pop(i)
10     else:
11         print(num_list[i])
12
13 print(num_list)

这回不会报异常了,但是打印结果如下:

[1, 2, 3, 4, 5]
1
4
5
[1, 3, 4, 5]

虽然最后,list中的元素[2]确实被删除掉了,但是,在循环中的打印结果不对,少打印了[3]。

思考了下,知道了原因,当符合条件,删除元素[2]之后,后面的元素全部往前移,于是[3, 4, 5]向前移动,那么元素[3]的索引,就变成了之前[2]的索引(现在[3]的下标索引变为1了),后面的元素以此类推。可是,下一次for循环的时候,是从下标索引2开始的,于是,取出了元素[4],就把[3]漏掉了。

再次修改代码,结果一样,丝毫没有改观:

 1 num_list = [1, 2, 3, 4, 5]
 2 print(num_list)
 3
 4 for item in num_list:
 5     if item == 2:
 6         num_list.remove(item)
 7     else:
 8         print(item)
 9
10 print(num_list)

找出问题的根本原因所在,想要找到正确的方法,也并不难,再次修改代码:

 1 num_list = [1, 2, 3, 4, 5]
 2 print(num_list)
 3
 4 i = 0
 5 while i < len(num_list):
 6     if num_list[i] == 2:
 7         num_list.pop(i)
 8         i -= 1
 9     else:
10         print(num_list[i])
11
12     i += 1
13
14 print(num_list)

执行结果,完全正确:

[1, 2, 3, 4, 5]
1
3
4
5
[1, 3, 4, 5]

我的做法是,既然用for循环不行,那就换个思路,用while循环来搞定。每次while循环的时候,都会去检查list的长度(i < len(num_list)),这样,就避免了索引溢出,然后,在符合条件,删除元素[2]之后,

手动把当前下标索引-1,以使下一次循环的时候,通过-1后的下标索引取出来的元素是[3],而不是略过[3]。

当然,这还不是最优解,所以,我搜索到了通用的解决方案:

  1、倒序循环遍历;

  2、遍历拷贝的list,操作原始的list。

1、倒序循环:

 1 num_list = [1, 2, 3, 4, 5]
 2 print(num_list)
 3
 4 for i in range(len(num_list)-1, -1, -1):
 5     if num_list[i] == 2:
 6         num_list.pop(i)
 7     else:
 8         print(num_list[i])
 9
10 print(num_list)

执行结果完全正确

解释正序循环时删除就有问题,而倒序循环时删除就ok

删除元素[2]之后,下一次循环的下标索引为2,但此时,里面存放的是[4],于是就把[3]给漏了。

2)倒序循环时删除

删除元素[2]后,[3, 4, 5]往前挤,但是没关系,因为下一次循环的下标索引为0,里面存放的是[1],所以正是我们所期望的正确的元素值。

2、遍历拷贝的list,操作原始的list

 1 num_list = [1, 2, 3, 4, 5]
 2 print(num_list)
 3
 4 for item in num_list[:]:
 5     if item == 2:
 6         num_list.remove(item)
 7     else:
 8         print(item)
 9
10 print(num_list)

原始的list是num_list,那么其实,num_list[:]是对原始的num_list的一个拷贝,是一个新的list,所以,我们遍历新的list,而删除原始的list中的元素,则既不会引起索引溢出,最后又能够得到想要的最终结果。此方法的缺点可能是,对于过大的list,拷贝后可能很占内存。那么对于这种情况,可以用倒序遍历的方法来实现

原文地址:https://www.cnblogs.com/zhouziyuan/p/10137086.html

时间: 2024-10-14 15:53:57

Python的list循环遍历中,删除数据的正确方法的相关文章

用angularjs在循环遍历中绑定ng-model(转载---CSDN博客 )

用angularjs在循环遍历中绑定ng-model CSDN博客 原文  http://blog.csdn.net/chen2991101/article/details/19764263 angularjs的双向绑定非常的好用,当修改了一个地方的值后另外一个地方也同步修改了,如果用平时的js来写的话需要写很多代码,但是用了angularjs后只需要几行代码就能轻松搞定. 想做一个类似于淘宝的改价的功能,就是当用户拍下了宝贝后卖家给你调价的那个功能,界面就像这样: 当修改了折扣或者直接填写了优

MySQL中删除数据的两种方法

转自:http://blog.csdn.net/apache6/article/details/2778878 在MySQL中有两种方法可以删除数据,一种是DELETE语句,另一种是TRUNCATE TABLE语句. DELETE语句可以通过WHERE对要删除的记录进行选择.而使用TRUNCATE TABLE将删除表中的所有记录.因此,DELETE语句更灵活. 如果要清空表中的所有记录,可以使用下面的两种方法: DELETE FROM table1 TRUNCATE TABLE table1 其

遍历List过程中删除元素的正确做法(转)

遍历List过程中删除元素的正确做法   public class ListRemoveTest {     3 public static void main(String[] args) { 4         List<Integer> list = new ArrayList<Integer>(); 5         list.add(1); 6         list.add(2); 7         list.add(2); 8         list.add(

该 ISAM 不支持在链接表中删除数据。

使用OleDB方式操作Excel,删除表中的数据时提示该错误 相关代码: 连接字符串: //定义OleDB连接字符串 string strConn = "Provider=Microsoft.Ace.OleDb.12.0;Persist Security Info=False;" + "data source=" + @excelPath + ";Extended Properties='Excel 12.0; HDR=yes; IMEX=10'"

PatentTips - 在物联网中进行数据过滤的方法和装置

背景技术 [0001] 本发明涉及物联网,特别涉及在物联网进行数据过滤的方法和装置. [0002] 物联网是新一代信息技术的重要组成部分,特指物物相连的网络.具体地,物联网是指通过各种信息传感设备,如传感器.射频识别(RFID)技术.全球定位系统.红外感应器.激光扫描器.气体感应器等各种装置与技术,实时采集任何需要监控.连接.互动的物体或过程,采集其声.光.热.电.力学.化学.生物.位置等各种需要的信息,与互联网结合形成的一个巨大网络.物联网目的是实现物与物.物与人.所有的物品与网络的连接,以方

复习 使用for、while循环遍历文件,数据类型转换

1. python访问文件 通过内置函数open打开文件,看一下open函数解释: 打开文件 返回的是一个文件对象 fd = open('/tmp/tmp.txt') 查看他的方法: 关闭文件: fd.close() 向文件内写入: fd = open('/tmp/tmp.txt', 'w') 这样打开文件等于重写文件,文件原有的内容就覆盖掉了 fd.write("a") 这样写入文件,写入文件后不能查看到,我们必须把他关闭: fd.close() 关闭之后,就可以查看到文件内的信息了

ODI中删除数据的处理

一.前提知识:数据从源数据库向数据仓库抽取时,一般采用以下几种方式: 全抽取模式如果表的数据量较小,则可以采取全表抽取方式,以TRUNCATE/INSERT方式进行数据抽取. 基于时间戳的抽取模式如果源数据表是不可更新的数据(如大多数事务处理数据)或者是不可删除数据(只能失效历史记录的情况),则根据变更时间戳,抽取最新变更的数据进行同步. 日志分析如果没有更新时间戳,或者源数据存在删除的情况,则可以进行日志分析,来执行最新数据变更的同步. 说明:时间戳的方式如果要处理删除数据的情况,需要在源表创

python连接mysql循环插入千万条数据脚本

之前都是在mysql的存储过程中插入数据,毕竟mysql语法函数有限,很多都有限制.突然想到学了python正好可以练练手. 首先需要安装pymysql模块包(模块包安装请自行百度) 1 #encoding:utf-8 2 import pymysql 3 import time 4 import random 5 #连接mysql 6 db = pymysql.connect('14.29.249.74','kx_admin','Yjh7yC0L7L1G1k6qXKwb','ilock') 7

小程序 循环遍历 传参数 获取参数的方法

//循环操作 block包裹着被循环的模板 <block wx:for="{{post_content}}" wx:for-item="item" wx:for-index="index" wx:key="index"> <!-- {{...item}}展开这个对象 --> <!-- data-postId={{item.postId}}自定义属性 --> <view catchtap