繁体   English   中英

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

[英]How to remove duplicates, by sublist item subset, in a list of lists in 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)

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

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

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任何子列表的前两个元素时才评估第一个表达式。 查看清单推导中的文档以获取更多信息。
  2. 知道set.add总是返回None 因此used.add(tuple(x[:2])) or x总是计算为x
  3. 由于list不可散列,因此我们需要将子列表的前两个元素转换为不可变的(例如元组)。

最后,如果您不熟悉这种模式,就会出现@wim,这可能很难理解,并且在Python中“可读性很重要”。 因此,如果您要编写将共享的代码,请考虑将其更改为显式的for循环或使用其他方法。

您可以将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]])

或使用简单的旧for循环:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM