【问题标题】:Python all combinations of a list of listsPython列表列表的所有组合
【发布时间】:2015-10-14 15:56:20
【问题描述】:

所以我有一个字符串列表

[['a','b'],['c','d'],['e','f']]

我想得到所有可能的组合,结果是

[['a','b'],['c','d'],['e','f'],
 ['a','b','c','d'],['a','b','e','f'],['c','d','e','f'],
 ['a','b','c','d','e','f']]

到目前为止我已经想出了这个代码sn-p

input = [['a','b'],['c','d'],['e','f']]
combs = []
for i in xrange(1, len(input)+1):
    els = [x for x in itertools.combinations(input, i)]
    combs.extend(els)
print combs

主要关注this post 中的答案。

但这会导致

[(['a','b'],),(['c','d'],),(['e','f'],),
 (['a','b'],['c','d']),(['a','b'],['e','f']),(['c','d'],['e','f']),
 (['a','b'],['c', 'd'],['e', 'f'])]

我目前很困惑,试图找到一种优雅的、pythonic 的方式来解包这些元组。

【问题讨论】:

    标签: python list tuples combinations itertools


    【解决方案1】:

    您可以使用itertools.chain.from_iterable 将列表元组扁平化为列表。示例 -

    import itertools
    input = [['a','b'],['c','d'],['e','f']]
    combs = []
    for i in xrange(1, len(input)+1):
        els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)]
        combs.extend(els)
    

    演示 -

    >>> import itertools
    >>> input = [['a','b'],['c','d'],['e','f']]
    >>> combs = []
    >>> for i in range(1, len(input)+1):
    ...     els = [list(itertools.chain.from_iterable(x)) for x in itertools.combinations(input, i)]
    ...     combs.extend(els)
    ...
    >>> import pprint
    >>> pprint.pprint(combs)
    [['a', 'b'],
     ['c', 'd'],
     ['e', 'f'],
     ['a', 'b', 'c', 'd'],
     ['a', 'b', 'e', 'f'],
     ['c', 'd', 'e', 'f'],
     ['a', 'b', 'c', 'd', 'e', 'f']]
    

    【讨论】:

    • 不错。我经常对itertools 的强大功能感到惊讶。
    • 完美。正是我想要的。谢谢!
    【解决方案2】:

    这种目标的一个想法是根据一个非常简单的规则将整数从[0..2**n-1] 映射到所有目标元素,其中 n 是子列表的数量: 如果(2**k)&i!=0 超过[0..2**n-1],则取索引k 的元素。换句话说,i 必须按位读取,并且对于每个位集,都保留来自 l 的相应元素。从数学的角度来看,它是实现您想要做的最干净的方法之一,因为它非常严格地遵循集合各部分的定义(对于具有 n 个元素的集合,您恰好有 2**n 部分)。

    没有尝试过,但类似的东西应该可以:

    l = [['a','b'],['c','d'],['e','f']]                                                    
    n = len(l)
    output = []
    for i in range(2**n):
        s = []
        for k in range(n):
            if (2**k)&i: s = s + l[k]
        output.append(s)
    

    如果您不想要空列表,只需将相关行替换为:

    for i in range(1,2**n):
    

    【讨论】:

      【解决方案3】:

      如果你想要所有的组合,你可以考虑这个简单的方法:

      import itertools
      
      a = [['a','b'],['c','d'],['e','f']]
      a = a + [i + j for i in a for j in a if i != j] + [list(itertools.chain.from_iterable(a))]
      

      【讨论】:

      • 如果原始列表包含 4 个列表,那么这将不包含长度为 3 的结果组合。
      • @Matt M. 是的,你是对的,我没有考虑列表包含 4 个列表,仅显示一个简单的案例。如果列表超过 3 个,Anand S Kumar 的方法将是您需要的方法。谢谢你告诉我。
      【解决方案4】:

      使用理解列表:

      combs=[sum(x,[]) for i in range(len(l)) for x in itertools.combinations(l,i+1)]
      

      【讨论】:

        猜你喜欢
        • 2010-10-22
        • 1970-01-01
        • 2014-07-31
        • 1970-01-01
        • 2015-10-13
        • 1970-01-01
        • 2018-08-19
        • 1970-01-01
        相关资源
        最近更新 更多