【问题标题】:Combinations of set elements with replacements, with a maximum number of repetitions集合元素与替换的组合,最大重复次数
【发布时间】:2022-10-15 17:15:32
【问题描述】:

问题:

  • 我有一个没有重复的元素列表(基本上是一组);
  • 我想要一个列表,其中包含长度L 的所有组合,每个元素的重复次数不超过r

完成此任务的最佳pythonic方法是什么?

可能对this answer 进行一些调整?...

【问题讨论】:

    标签: python python-3.x combinatorics


    【解决方案1】:

    您可以使用itertools.combinations_with_replacement,然后使用collections.Counter 过滤掉重复元素过多的元素。

    from itertools import combinations_with_replacement
    from collections import Counter
    
    a = ["h","e","l","o","w","r","d"]
    L, r = 3, 2
    result = []
    
    for combo in combinations_with_replacement(a, L):
        tally = Counter(combo)
        if max(tally.values()) <= r:
            result.append(combo)
    
    print(result)
    

    输出

    [('h', 'h', 'e'), ('h', 'h', 'l'), ('h', 'h', 'o'), ('h', 'h', 'w'), ('h', 'h', 'r'), ('h', 'h', 'd'), ('h', 'e', 'e'), ('h', 'e', 'l'), ('h', 'e', 'o'), ('h', 'e', 'w'), ('h', 'e', 'r'), ('h', 'e', 'd'),
     ('h', 'l', 'l'), ('h', 'l', 'o'), ('h', 'l', 'w'), ('h', 'l', 'r'), ('h', 'l', 'd'), ('h', 'o', 'o'), ('h', 'o', 'w'), ('h', 'o', 'r'), ('h', 'o', 'd'), ('h', 'w', 'w'), ('h', 'w', 'r'), ('h', 'w', 'd'),
     ('h', 'r', 'r'), ('h', 'r', 'd'), ('h', 'd', 'd'), ('e', 'e', 'l'), ('e', 'e', 'o'), ('e', 'e', 'w'), ('e', 'e', 'r'), ('e', 'e', 'd'), ('e', 'l', 'l'), ('e', 'l', 'o'), ('e', 'l', 'w'), ('e', 'l', 'r'),
     ('e', 'l', 'd'), ('e', 'o', 'o'), ('e', 'o', 'w'), ('e', 'o', 'r'), ('e', 'o', 'd'), ('e', 'w', 'w'), ('e', 'w', 'r'), ('e', 'w', 'd'), ('e', 'r', 'r'), ('e', 'r', 'd'), ('e', 'd', 'd'), ('l', 'l', 'o'),
     ('l', 'l', 'w'), ('l', 'l', 'r'), ('l', 'l', 'd'), ('l', 'o', 'o'), ('l', 'o', 'w'), ('l', 'o', 'r'), ('l', 'o', 'd'), ('l', 'w', 'w'), ('l', 'w', 'r'), ('l', 'w', 'd'), ('l', 'r', 'r'), ('l', 'r', 'd'),
     ('l', 'd', 'd'), ('o', 'o', 'w'), ('o', 'o', 'r'), ('o', 'o', 'd'), ('o', 'w', 'w'), ('o', 'w', 'r'), ('o', 'w', 'd'), ('o', 'r', 'r'), ('o', 'r', 'd'), ('o', 'd', 'd'), ('w', 'w', 'r'), ('w', 'w', 'd'),
     ('w', 'r', 'r'), ('w', 'r', 'd'), ('w', 'd', 'd'), ('r', 'r', 'd'), ('r', 'd', 'd')]
    

    【讨论】:

    • 这行得通,谢谢。想知道这个解决方案离最佳解决方案还有多远:)
    • 如果您想知道“最佳”,请计算生成的项目数量与接受的项目数量。我怀疑这取决于列表的长度、您访问的数量以及“r”是什么。
    • @mavzolej 看到来自 FrankYellin 的消息
    【解决方案2】:

    这是一个自定义实现,可以避免所有不必要的计算:

    def comb(elements, size, repeat):
        yield from _comb(elements, size, repeat, ()) 
    
    def _comb(elements, size, repeat, accum):
        if size == 0:
            yield accum
            return
    
        elem, *rest = elements
    
        min_count = max(size-repeat*len(rest), 1)
        max_count = min(size, repeat) + 1 
        for count in range(min_count, max_count):
            new_accum = accum + (elem, ) * count
            yield from _comb(rest, size-count, repeat, new_accum)
    

    例子:

    >>> list(comb([2,3,4,5], size=7, repeat=3))
    [(2, 3, 4, 4, 5, 5, 5), (2, 3, 4, 4, 4, 5, 5), (2, 3, 3, 4, 5, 5, 5), (2, 3, 3, 4, 4, 5, 5), (2, 3, 3, 4, 4, 4, 5), (2, 3, 3, 3, 4, 5, 5), (2, 3, 3, 3, 4, 4, 5), (2, 3, 3, 3, 4, 4, 4), (2, 2, 3, 4, 5, 5, 5), (2, 2, 3, 4, 4, 5, 5), (2, 2, 3, 4, 4, 4, 5), (2, 2, 3, 3, 4, 5, 5), (2, 2, 3, 3, 4, 4, 5), (2, 2, 3, 3, 4, 4, 4), (2, 2, 3, 3, 3, 4, 5), (2, 2, 3, 3, 3, 4, 4), (2, 2, 2, 3, 4, 5, 5), (2, 2, 2, 3, 4, 4, 5), (2, 2, 2, 3, 4, 4, 4), (2, 2, 2, 3, 3, 4, 5), (2, 2, 2, 3, 3, 4, 4), (2, 2, 2, 3, 3, 3, 4)]
    

    如果遇到递归深度问题(如果列表中的元素太多),您当然可以将其转换为迭代变体。

    【讨论】:

      【解决方案3】:

      查看itertools中的combinations_with_replacement()

      import itertools
      for combination in itertools.combinations_with_replacement(['red', 'green', 'blue', 'yellow'], r=3):
           print(combination)
      
      ('red', 'red', 'red')
      ('red', 'red', 'green')
      ('red', 'red', 'blue')
      ('red', 'red', 'yellow')
      ('red', 'green', 'green')
      ('red', 'green', 'blue')
      ('red', 'green', 'yellow')
      ('red', 'blue', 'blue')
      ('red', 'blue', 'yellow')
      ('red', 'yellow', 'yellow')
      ('green', 'green', 'green')
      ('green', 'green', 'blue')
      ('green', 'green', 'yellow')
      ('green', 'blue', 'blue')
      ('green', 'blue', 'yellow')
      ('green', 'yellow', 'yellow')
      ('blue', 'blue', 'blue')
      ('blue', 'blue', 'yellow')
      ('blue', 'yellow', 'yellow')
      ('yellow', 'yellow', 'yellow')
      >>> 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-10
        • 1970-01-01
        相关资源
        最近更新 更多