从列表中删除某些项目重复的列表
我试图从列表中删除具有相同第一和第三项但仅保留第一项的列表。示例列表和输出:从列表中删除某些项目重复的列表
li=[ [2,4,5], [1,3,5], [1,6,5] ]
output_list = [ [2,4,5], [1,3,5] ]
我写的代码需要很长时间才能执行,因为原始列表包含数百万个列表。
b_li = []
output_list = []
for x in li:
s = [ x[0], x[2] ]
if s not in b_li:
b_li.append(s)
output_list.append(x)
我该如何改进代码?提前致谢。
的改进版本:
b_li = set()
output_list = []
b_li_add = b_li.add
output_list_append = output_list.append
for x in li:
s = (x[0], x[2])
if s not in b_li:
b_li_add(s)
output_list_append(x)
的变化是:
- 使用
set()
为b_li
这使得查找更快。 - 将
s
转换为一个元组,因为不需要将唯一的第一个和第三个元素存储为列表。 - 减少功能查找,加快代码。
使用一组来存储看到的元素。这是更快:
seen = set()
res = []
for entry in li:
cond = (entry[0], entry[2])
if cond not in seen:
res.append(entry)
seen.add(cond)
[[2, 4, 5], [1, 3, 5]]
加成
此外,在想着告诉变量的名称通常也花时间花。通常情况下,最初的解决方案比预期的要长得多。
+1这是一个简单,干净的解决方案。 –
谢谢,这是一个巨大的飞跃:) –
这是一个基于@ iurisilvio的iterator评论并与来自其他人的set
为基础的解决方案结合使用itertools.compress
的解决方案。 而不是从输入列表中的元素构建output_list
,包含布尔值的selector
列表是相对于输入列表中的元素建立的。值为True
表示输入列表中的相应元素应保留在输出中。然后可以通过itertools.compress
将selector
应用于输入列表以产生可迭代的输出。
from itertools import compress
li=[ [2,4,5], [1,3,5], [1,6,5] ]
b_li = set()
selectors = []
for x in li:
s = (x[0], x[2])
if s not in b_li:
b_li.add(s)
selectors.append(True)
else:
selectors.append(False)
for x in compress(li, selectors):
print x
[2, 4, 5]
[1, 3, 5]
利用OrderedDict
和词典具有唯一键的事实。
>>> from collections import OrderedDict
>>> li=[ [2,4,5], [1,3,5], [1,6,5] ]
>>> OrderedDict(((x[0], x[2]), x) for x in reversed(li)).values()
[[1, 3, 5], [2, 4, 5]]
使用一个集合而不是一个列表来记录看到的第一个/最后一个对。 – Marcin
根据您的使用情况,您可以返回迭代器而不是创建新列表。它会为你节省大量的内存。 – iurisilvio
可能重复? http://*.com/questions/15037226/python-remove-duplicate-items-from-nested-list?rq=1 –