获取唯一的多组列表

时间:2014-04-29 05:50:31

标签: python collections unique combinations multiset

如何在Python中统一以下列表:

all_the_ways = [(5,), (2, 2, 1), (2, 1, 2), (2, 1, 1, 1), (1, 2, 2),\
                (1, 2, 1, 1), (1, 1, 2, 1), (1, 1, 1, 2), (1, 1, 1, 1, 1)]

所需的输出是:

[(5,), (2, 2, 1), (2, 1, 1, 1), (1, 1, 1, 1, 1)]

即。我需要摆脱具有相同数字但不同顺序的元组。

我试过

set(all_the_ways)

但它只转置元素。

当我做的时候

list(map(set, all_the_ways))

事情变得更糟:

[{5}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1}]

换句话说,我需要将内部元组转换为允许多个相等项目的集合(set不适合),并且元素的排列不会改变集合本身(有点)比如C ++' multiset

6 个答案:

答案 0 :(得分:5)

这个怎么样:

list(set(tuple(sorted(s)) for s in all_the_ways))

输出:

[(1, 2, 2), (5,), (1, 1, 1, 1, 1), (1, 1, 1, 2)]

它会破坏每个元组的顺序。我认为这并不重要,因为包含相同数字集的元组在您的情况下被认为是相同的。这意味着,最后,输出列表可能包含不在原始输入中的元组,例如(归功于@thefourtheye):

all_the_ways = [(2, 1, 2), (2, 2, 1)]
# Output: [(1, 2, 2)]

这可能是也可能不是问题,如果是,您可以使用其他优秀答案中已经提到的更强大的解决方案。

答案 1 :(得分:3)

使用collections.Counter()标识唯一的多重集:

>>> from collections import Counter

>>> all_the_ways = [(5,), (2, 2, 1), (2, 1, 2), (2, 1, 1, 1), (1, 2, 2),\
                (1, 2, 1, 1), (1, 1, 2, 1), (1, 1, 1, 2), (1, 1, 1, 1, 1)]
>>> result = []
>>> seen = set()
>>> for tup in all_the_ways:
        key = tuple(sorted(Counter(tup).items())) # unique signature
        if key not in seen:
            result.append(tup)
        seen.add(key)

>>> result
[(5,), (2, 2, 1), (2, 1, 1, 1), (1, 1, 1, 1, 1)]

答案 2 :(得分:2)

如果订单无关紧要,您可以使用此

from collections import Counter
>>> {frozenset(Counter(tup).items()):tup for tup in data}.values()
# [(1, 2, 2), (1, 1, 1, 2), (1, 1, 1, 1, 1), (5,)]

如果您想维护订单,

from collections import Counter, OrderedDict
OrderedDict([frozenset(Counter(tup).items()),tup] for tup in data).values()
# [(5,), (1, 2, 2), (1, 1, 1, 2), (1, 1, 1, 1, 1)]

在我们依赖frozenset的两个解决方案中,因为set个对象不可编辑,因为它们是可变的。在第一种情况下,我们构造一个字典,其中数字的频率(用Counter确定)作为键,当前元组作为对应的值。字典构造完成后,我们将获取与元组相对应的所有值。

在第二种情况下,我们只需使用OrderedDict来维护订单。

答案 3 :(得分:1)

可能是这个?:

result = {tuple(sorted(x)) for x in all_the_ways}

答案 4 :(得分:1)

尝试

from collections import OrderedDict
print OrderedDict.fromkeys(map(lambda x: tuple(sorted(x)), all_the_ways)).keys()

print set(map(lambda x: tuple(sorted(x)), all_the_ways))

答案 5 :(得分:0)

我认为如果它们包含相同的值,则认为两个元素“相等”,无论顺序如何。

因此,您可以通过对每个元组进行“规范化”,将其转换回元组(以便它们可以播放),并再次使用set删除重复项:

set( tuple(sorted(tup)) for tup in all_the_ways )

您还可以使用OrderedSet代替set来保留原始的“外部”订单。