【问题标题】:Itertools Combinations No Repeats: Where rgb is equivelant to rbg etcItertools 组合无重复:其中 rgb 等价于 rgb 等
【发布时间】:2017-06-01 11:56:20
【问题描述】:

我正在尝试使用 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) 的变体,但这感觉有点“非 Python 式”。

【问题讨论】:

  • 那么,为什么不从四个有效输出中选择一个呢?
  • 对不起,如果不清楚,但我想返回所有有效的组合,但我认为问题中提到的“有效”。
  • 那么rrb rrg 等呢?另外,如果您确定您唯一有效的输出是rrrgggbbbrgb,那么只需输出它们,就没有什么可计算的了?
  • See this question.rgb 视为容量与其计数相等的箱。然后,在接受的答案中应用算法。

标签: python combinations itertools


【解决方案1】:

您可以使用set 丢弃重复项。

在您的情况下,字符数是您识别重复项的方式,因此您可以使用collections.Counter。为了将它们保存在set 中,您需要将它们转换为frozensets(因为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) 的一种变体 - 所以它可能是“相当 Python 的”。

【讨论】:

  • 谢谢你。虽然它没有产生我想要的东西,但这项技术对我来说是新的,你的链接很有见地,所以 +1。
【解决方案2】:

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

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']

这将比创建所有可能的组合并随后过滤有效的组合更有效。

【讨论】:

    【解决方案3】:

    尚不完全清楚您要返回什么。这取决于迭代时首先出现的内容。例如,如果首先找到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']]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-27
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      • 2021-02-06
      • 2023-03-15
      • 2012-02-21
      • 2011-03-18
      相关资源
      最近更新 更多