Itertools组合无重复:rgb与rbg等等

时间:2017-06-01 11:56:20

标签: python combinations itertools

我尝试使用itertools.combinations返回唯一组合。我已经搜索了几个类似的问题,但未能找到答案。

一个例子:

>>> import itertools
>>> e = ['r','g','b','g']
>>> list(itertools.combinations(e,3))
[('r', 'g', 'b'), ('r', 'g', 'g'), ('r', 'b', 'g'), ('g', 'b', 'g')]

就我的目的而言,(r,g,b)与(r,b,g)相同,所以我想只返回(rgb),(rgg)和(gbg)。

这只是一个说明性的例子,我想忽略所有这些'重复'。列表e最多可包含5个元素。每个单独的元素可以是r,g或b。始终寻找e中3个元素的组合。

具体而言,以下是我希望调用的唯一组合'有效':(rrr),(ggg),(bbb),(rgb)。

所以也许问题归结为如何将(rgb)的任何变化视为等于(rgb),因此忽略它。

我可以使用itertools来实现这一目标,还是需要编写自己的代码来删除“重复”内容。这里?如果没有itertools解决方案,那么我可以轻松检查每个是否是(rgb)的变体,但这感觉有点“非pythonic”#。

3 个答案:

答案 0 :(得分:2)

您可以使用set来放弃重复项。

在您的情况下,字符数是您识别重复项的方式,因此您可以使用collections.Counter。要将它们保存在set中,您需要将它们转换为frozenset s(因为Counter不可播放):

>>> import itertools
>>> from collections import Counter
>>> e = ['r','g','b','g']
>>> result = []
>>> seen = set()
>>> for comb in itertools.combinations(e,3):
...     cnts = frozenset(Counter(comb).items())
...     if cnts in seen:
...         pass
...     else:
...         seen.add(cnts)
...         result.append(comb)
>>> result
[('r', 'g', 'b'), ('r', 'g', 'g'), ('g', 'b', 'g')]

如果要将它们转换为字符串,请使用:

result.append(''.join(comb))  # instead of result.append(comb)

它将给出:

['rgb', 'rgg', 'gbg']

这种方法是unique_everseen recipe (itertools module documentation)的一种变体 - 所以它可能是“相当pythonic”。

答案 1 :(得分:1)

根据您对“有效输出”的定义,您可以直接构建它们:

from collections import Counter

# Your distinct values
values = ['r', 'g', 'b']

e = ['r','g','b','g', 'g']

count = Counter(e)
# Counter({'g': 3, 'r': 1, 'b': 1})

# If x appears at least 3 times, 'xxx' is a valid combination  
combinations = [x*3 for x in values if count[x] >=3]

# If all values appear at least once, 'rgb' is a valid combination
if all([count[x]>=1 for x in values]):
    combinations.append('rgb')

print(combinations)
#['ggg', 'rgb']

这比创建所有可能的组合以及之后过滤有效组合更有效。

答案 2 :(得分:0)

您想要归还的并不完全清楚。这取决于迭代时首先出现的内容。例如,如果首先找到gbr,则rgb将作为副本丢弃:

import itertools

e = ['r','g','b','g']       
s = set(e)
v = [s] * len(s)

solns = []

for c in itertools.product(*v):
    in_order = sorted(c)
    if in_order not in solns:
        solns.append(in_order)

print solns  

这会给你:

[['r', 'r', 'r'], ['b', 'r', 'r'], ['g', 'r', 'r'], ['b', 'b', 'r'], ['b', 'g', 'r'], ['g', 'g', 'r'], ['b', 'b', 'b'], ['b', 'b', 'g'], ['b', 'g', 'g'], ['g', 'g', 'g']]