5

如果我有一个元组列表,其中每个元组代表变量、abc如何消除冗余元组?

冗余元组是那些简单ab互换,但c相同的元组。所以对于这个例子:

tups = [(30, 40, 50), (40, 30, 50), (20, 48, 52), (48, 20, 52)]

我的最终名单应该只包含一半的条目。一种可能的输出:

tups = [(30, 40, 50), (20, 48, 52)]

其他

tups = [(40, 30, 50), (20, 48, 52)]

等等

有没有一种简单的 Pythonic 方法可以做到这一点?

我尝试使用集合,但(30, 40, 50)与 不同(40, 30, 50),但对我来说这些是多余的,我只想保留其中一个(没关系,但如果我可以选择,我更喜欢低价值订单) . 如果有办法对元组的前 2 个元素进行排序,那么使用集合就可以了。

我确信我可以拼凑出一个可行的解决方案(也许将元组转换为列表作为中间步骤),但我只是想看看是否有一种我不熟悉的简单而明显的方法来做到这一点。

PS:这个问题部分是由PE #39引起的。但即使抛开这个 PE 问题,我现在也很好奇如何轻松地(或是否)做到这一点。

编辑

只是为那些不熟悉 PE #39 - 的人提供一些背景信息 - a, b, 并c表示直角三角形的边,所以我正在检查 if a**2 + b**2 == c**2,清楚的顺序ab无关紧要。

4

5 回答 5

7
set([(a,b,c) if a<b else (b,a,c) for a,b,c in tups])
于 2012-07-28T23:32:44.543 回答
4
tups = [(30, 40, 50), (40, 30, 50), (20, 48, 52), (48, 20, 52)] 
no_duplicates = list(set(tuple(sorted(tup)) for tup in tups))

当然这是假设每个元组的第三个元素总是每个元组中最大的元素,否则,这样做:

no_duplicates = list(set(tuple(sorted(tup[:2])) + (tup[2],) for tup in tups))

正如 WolframH 建议的那样,表达式tuple(sorted(tup[:2])) + (tup[2],)可以写为tuple(sorted(tup[:2])) + tup[2:],这是有利的,因为它可以推广到tuple(sorted(tup[:i])) + tup[i:],其中i可以是任何想要将已排序元素与未排序元素分开的点。

于 2012-07-28T23:27:38.920 回答
4

从您的问题来看,您的元组的前两个元素似乎在元组中形成了一个子单元。因此,将数据重组为一个元组和第三个数字的元组似乎是有意义的,其中第一个元组是按排序顺序排列的前两个数字。然后你自然可以使用集合:

>>> newTups = [(tuple(sorted([a, b])), c) for a, b, c in tups]
>>> newTups
[((30, 40), 50), ((30, 40), 50), ((20, 48), 52), ((20, 48), 52)]
>>> set(newTups)
set([((20, 48), 52), ((30, 40), 50)])
于 2012-07-28T23:29:13.167 回答
2

将您的每个元组转换为 afrozenset并创建set这些frozensets。

tups = [(30, 40, 50), (40, 30, 50), (20, 48, 52), (48, 20, 52)]

frozen_sets = { frozenset(x) for x in tups }

tups2 = [tuple(x) for x in frozen_sets]

这是有效frozenset([1,2,3]) == frozenset([3,1,2])的,因为与元组相比,其中(1,2,3) != (3,1,2).

您必须将元组转换为frozensets 而不是 simple sets,因为当您尝试使一个集合成为另一个集合的成员时会出现以下错误:

TypeError: unhashable type: 'set'

frozensets 是可散列的,因此避免了这个问题。

于 2012-07-28T23:46:25.707 回答
1

如果您不关心前两个元素的顺序,那么您真的不想使用 3-uples :只需转换为丢弃您不需要的信息的新数据结构。

result = {({x[0],x[1]},x[2]) for x in tups}
于 2012-07-28T23:27:42.040 回答