例如,假设我有一个列表:
list_ = [(4,5),(5,4),(5,4),(8,10),(10,8),(9,3),(5,4),(10,8),(8,8)]
如何去除所有反向元组,所以剩下的是:
list_ = [(4,5),(8,10),(9,3),(8,8)]
?
这是我正在做的一个个人项目,我写了一些东西来检测反向元组并删除它们,但是只删除其中一个反向元组(而不是全部)。我认为字典在这里很有用,但不确定如何实现它
答案 0 :(得分:4)
我会写一个很好的老式for
循环。该解决方案保证了以下几点:保留任何反向元组的第一个,输出列表与输入的顺序相同,不对输入元组的长度做任何假设。
list_ = [(4,5),(5,4),(5,4),(8,10),(10,8),(9,3),(5,4),(10,8),(8,8)]
output, seen = [], set()
for item in list_:
t1 = tuple(item)
if t1 not in seen and tuple(reversed(item)) not in seen:
seen.add(t1)
output.append(item)
print(output)
# [(4, 5), (8, 10), (9, 3), (8, 8)]
答案 1 :(得分:3)
对于所有长度为2的元组,您可以将frozenset
与文档中的itertools
unique_everseen
recipe结合使用,more_itertools
和toolz
第三方库中也提供这些功能:>
from more_itertools import unique_everseen
list_ = [(4,5),(5,4),(5,4),(8,10),(10,8),(9,3),(5,4),(10,8),(8,8)]
res = list(unique_everseen(list_, key=frozenset))
[(4, 5), (8, 10), (9, 3), (8, 8)]
frozenset
是唯一项的无序但可哈希的集合。该解决方案假定您所有输入的长度均为2。因此,不会区分(8,)
和(8, 8)
。
对于不同长度的元组,您可以对配方进行一些小的调整:
def unique_everseen_custom(it):
seen = set()
seen_add = seen.add
for tup in it:
if (tup not in seen) and (tup[::-1] not in seen):
seen_add(tup)
seen_add(tup[::-1])
yield tup
res = list(unique_everseen_custom(list_))
答案 2 :(得分:2)
如果我们认为您所有的元组都是duplet,并且您想要保留唯一值:
list_ = [(4,5),(5,4),(5,4),(8,10),(10,8),(3,9),(5,4)]
然后我们对元组进行排序:
list_ = [tuple(sorted(t)) for t in list_]
然后使用一组删除重复项:
list_ = list(set(list_))