我试图从列表中删除列表,这些列表具有相同的第一个和第三个项目但仅保留第一个项目。示例列表和输出:
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)
如何改进代码?提前谢谢。
答案 0 :(得分:2)
使用一组来存储所看到的元素。那更快:
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]]
<强> ADDITION 强>
此外,花在考虑告知变量名称上的时间通常也很好。通常情况下,首先是扔掉的解决方案比预期的要长得多。
答案 1 :(得分:2)
改进版本:
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
转换为元组,因为无需将唯一的第一个和第三个元素存储为列表。答案 2 :(得分:1)
利用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]]
答案 3 :(得分:0)
这是一个基于@ iurisilvio的迭代器评论的解决方案,它使用itertools.compress
和其他基于set
的解决方案。
不是从输入列表中的元素构建output_list
,而是根据输入列表中的元素以一对一的方式构建包含布尔值的selector
列表。值True
表示输入列表中的相应元素应保留在输出中。然后,selector
可以通过itertools.compress
应用于输入列表,以生成可迭代的输出。
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]