从列表中删除某些项目重复的列表

时间:2013-06-01 22:54:52

标签: python list

我试图从列表中删除列表,这些列表具有相同的第一个和第三个项目但仅保留第一个项目。示例列表和输出:

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)

如何改进代码?提前谢谢。

4 个答案:

答案 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]