python列表去重remove_对列表for循环中remove列表中元素异常问题

对列表for循环中remove列表中元素异常问题

问题

假设现在存在以下列表:

server_list = [

{'ip': '10.0.0.1', 'role': 'proxy'},

{'ip': '10.0.0.2', 'role': 'proxy'},

{'ip': '10.0.0.1', 'role': 'app'},

{'ip': '10.0.0.2', 'role': 'app'},

{'ip': '10.0.0.3', 'role': 'db'}

]

在某次批量操作中,需要对列表按照 ip

字段进行去重,以避免同一台机器重复操作。

简单的写了一下代码逻辑:

_server = []

for ele in server_list:

_ip = ele.get('ip')

if _ip:

if _ip in _server:

server_list.remove(ele)

else:

_server.append(_ip)

print len(server_list)

按照理解,这里执行完最后的输出应该只有 3 台机器,但实际执行结果却是 4

台机器。

分析

重新修改了代码,在 for 循环中打印每次执行的 ip 的值:

_server = []

for ele in server_list:

_ip = ele.get('ip')

print _ip # add this line

if _ip:

if _ip in _server:

server_list.remove(ele)

else:

_server.append(_ip)

最后执行结果如下:

10.0.0.1

10.0.0.2

10.0.0.1

10.0.0.3

发现实际列表有 5 个元素,但是 for 循环只执行了 4 次。

唯一一个比较可能出问题的点就是对列表的删除元素操作,尝试去掉删除操作,重新执行。

结果是输出了 5 个 ip,也就是正常的循环次数,所以问题出现在对列表删除操作中。

原因是不能在同一个列表 for

循环中对该列表进行删除元素操作。

然而这个问题在使用的 python2.7 版本中没有异常提示。容易出现认知差异如下:

之前的认知是,在列表的 for

循环开始时就已经处理所有需要循环的数据,

所以认为在循环中对列表的操作不会影响到循环的数据。

然而实际上,for

循环是实例获取列表长度通过索引下标取出本次循环需要处理的数据,

所以当删除列表中的元素时,列表的长度会发生了变化,for 循环就会受到影响。

解决

在理解清楚 for

循环的处理逻辑后,解决起来就很简单了。以下列出一些常规的方式:

利用 copy 数组循环

_server = []

_server_list_copy = list(server_list)

for ele in _server_list_copy:

_ip = ele.get('ip')

if _ip:

if _ip in _server:

server_list.remove(ele)

else:

_server.append(_ip)

也就是利用一个 copy

的数据进行循环,然后再循环中删除目标数据的元素,这样就不会循环数据。

需要注意的是,copy 数据不能简单的直接赋值,至少需要 shallow copy,

如果数组的元素存在嵌套情况,建议使用 deep copy,以保证两个数据完全不会干扰。

利用dict去重再赋值

_ip_server_dic = {}

for ele in server_list:

_ip = ele.get('ip')

if _ip:

_ip_server_dic[_ip] = ele

if _ip_server_dic:

server_list = _ip_server_dic.values()

因为需要关注的只是 ip 信息,其他信息比如 role

字段没有要求,

所以直接将需要去重字段的值作为key,原数据作为 value 创建一个字典。

最后再将字典的所有 value 取出来就可以拿到按 ip 字段去重后的列表。

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值