如何在Python的列表列表中删除子列表项子集的重复项?

时间:2018-03-04 17:36:18

标签: python

我在Python中有一个列表列表,其定义如下:[[2, 3, 5], [3, 3, 1], [2, 3, 8]],不是我想要删除重复的条目,但重复我的意思是每个列表的前两个元素匹配,例如,第一个和第三个列表有2个和3个作为它们的第一个和第二个元素,因此,我将它视为重复,并且在删除后我想要有最终列表:[[2, 3, 5], [3, 3, 1]]。目前,我有这样的事情:

arr = [[2, 3, 5], [3, 3, 1], [2, 3, 8]]

first = [item[0] for item in arr]
second = [item[1] for item in arr]
zipped = zip(first, second)

这将生成包含每个列表的前两个条目的元组列表。现在,我可以尝试获取重复条目的索引并从原始列表中删除这些索引。但是,有没有更短的方法来做我想要的?如果没有,这里获取重复索引的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

解决方案

您可以使用集来完成此任务:

arr = [[2, 3, 5], [3, 3, 1], [2, 3, 8]]

used = set()
[used.add(tuple(x[:2])) or x for x in arr if tuple(x[:2]) not in used]

返回

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

备注

  1. 仅在任何子列表的前两个元素不在used中时才评估第一个表达式。结帐the docs on list comprehensions了解详情。
  2. 知道set.add总是返回None。因此used.add(tuple(x[:2])) or x始终评估为x
  3. 我们需要将子列表的前两个元素转换为不可变的(例如元组),因为list不可用。
  4. 最后,如果你不熟悉这种模式,@ wim就会提起来,这很难理解,并且在Python中可读性很重要。"因此,如果您正在编写将要共享的代码,请考虑将其更改为显式for循环或使用其他方法。

答案 1 :(得分:2)

您可以使用collections.OrderedDict进行订单保留重复数据删除:

>>> d = OrderedDict(((x[0], x[1]), x) for x in reversed(L))
>>> print(*d.values())
[2, 3, 5] [3, 3, 1]

要保留最后一个而不是第一个,只需删除reversed

>>> OrderedDict(((x[0], x[1]), x) for x in L).values()
odict_values([[2, 3, 8], [3, 3, 1]])

或使用普通的旧循环:

def dedupe(iterable):
    seen = set()
    for x in iterable:
        first, second, *rest = x
        if (first, second) not in seen:
            seen.add((first, second))
            yield x