从元组列表中删除部分重复的元组

3
我有一个元组列表,如果其第一个项与列表中其他元组的第一个项匹配,则需要删除元组。第三个项目可能相同,也可能不同,因此我不能使用集合(我看过这个问题 - 无论顺序如何在python列表中抓取独特的元组,但这与我的问题不同)。
例如,如果我得到a
[(0, 13, 'order1'), (14, 27, 'order2'), (14, 27, 'order2.1'), 
 (0, 13, 'order1'), (28, 41, 'order3')]

我想要的输出是:

最初的回答

[(14, 27, 'order2'), (0, 13, 'order1'), (28, 41, 'order3')]

我使用以下代码获得了所需的输出。

最初的回答

for e, i in enumerate(a):
    r = [True if i[0] == k[0] and e != j else False for j, k in enumerate(a)]
    if any(r):
        a.pop(e)
pprint(a)

有更好的或更符合Python风格的方法来实现相同的功能吗?最初的回答。

如果你发现两个重复项,例如 (14, 27, 'order2')(14, 27, 'order2.1'),你如何知道要使用哪个第三项,'order2' 还是 'order2.1' - Joe Patten
元组中的第二个项目无关紧要吗? - Prune
1
@JoePatten 没关系,我可以选择其中任何一个 - ramd
在遍历列表时修改它是一个通常非常糟糕的想法。 - Prune
是的,在这种情况下,解决方案会有所不同;你需要同时保留(0, 0, "a")和(0, 1, "b")。 - Prune
显示剩余4条评论
3个回答

4

通常的方法是通过键入一个字典,以便通过任何你想要去重的内容进行分类,例如:

>>> a = [(0, 13, 'order1'), (14, 27, 'order2'), (14, 27, 'order2.1'), (0, 13, 'order1'), (28, 41, 'order3')] 
>>> print(*{tup[:2]: tup for tup in a}.values()) 
(0, 13, 'order1') (14, 27, 'order2.1') (28, 41, 'order3')

这是O(n)时间复杂度,比O(n log n)基于groupby的方法更优。


2
在迭代列表时,应避免就地修改列表。相反,您可以使用流行的itertools unique_everseen recipe,该方案也可在第三方more_itertools中获得。只需在key参数中使用operator.itemgetter即可:
from more_itertools import unique_everseen
from operator import itemgetter

res = list(unique_everseen(L, key=itemgetter(0, 1)))

这个解决方案需要O(n)的时间,但通常比基于字典的解决方案效率低,尽管它在意图上更清晰。

1
你可以在已分组、排序的列表中获取每个组的第一个元素:
from itertools import groupby
from operator import itemgetter

a = [(0, 13, 'order1'), (14, 27, 'order2'), (14, 27, 'order2.1'), (0, 13, 'order1'), (28, 41, 'order3')]

result = [list(g)[0] for k, g in groupby(sorted(a), key=itemgetter(0))]
print(result)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接