【问题标题】:Is there a pythonic way of permuting a list of list?有没有一种排列列表列表的pythonic方式?
【发布时间】:2016-09-28 10:59:55
【问题描述】:

我有一个包含唯一字符串的列表列表,我想生成任意数量的不同排序方式。该列表可能如下所示:

list = [[a], [b,c], [d], [e,f,g]]

列表的顺序需要相同,但我想在列表中打乱排序,然后将它们放在一个列表中,例如

list1 = [a,b,c,d,e,f,g]
list2 = [a,c,b,d,f,e,g]
...
...
listN = [a,c,b,d,f,g,e]

有什么好的pythonic方法可以实现这一点?我在 python 2.7 上。

【问题讨论】:

标签: python list python-2.7 permutation


【解决方案1】:
from itertools import permutations, product

L = [['a'], ['b','c'], ['d'], ['e', 'f', 'g']]

for l in product(*map(lambda l: permutations(l), L)):
    print([item for s in l for item in s])

产生:

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

【讨论】:

  • 你不需要 lambda;查看我添加到答案中的新版本。
  • @PM2Ring 啊,确实...旧习惯很难改掉,我想... ;)
【解决方案2】:

您可以通过获取子列表排列的笛卡尔积,然后展平生成的嵌套元组来做到这一点。

from itertools import permutations, product, chain

lst = [['a'], ['b', 'c'], ['d'], ['e', 'f', 'g']]

for t in product(*[permutations(u) for u in lst]):
    print([*chain.from_iterable(t)])

输出

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

如果您需要在 Python 2 中执行此操作,可以将打印行替换为:

print list(chain.from_iterable(t))

这是一个更紧凑的版本,灵感来自 ewcz 的回答:

for t in product(*map(permutations, lst)):
    print list(chain.from_iterable(t))

【讨论】:

    【解决方案3】:

    这可能不是最优雅的解决方案,但我认为它可以满足您的需求

    from itertools import permutations
    import numpy as np
    
    def fac(n):
        if n<=1:
            return 1
        else:
            return n * fac(n-1)
    
    lists = [['a'], ['b','c'], ['d'], ['e','f','g']]
    
    combined = [[]]
    for perm in [permutations(l,r=len(l)) for l in lists]:
        expanded = []
        for e in list(perm):
            expanded += [list(l) + list(e) for l in combined]
        combined = expanded
    
    ## check length
    
    print np.prod(map(fac,map(len,lists))), len(combined)
    
    print '\n'.join(map(str,combined))
    

    【讨论】:

      【解决方案4】:

      您可以展平列表,然后简单地生成其排列:

      from itertools import chain, permutations
      
      li = [['a'], ['b','c'], ['d'], ['e','f','g']]
      flattened = list(chain.from_iterable(li))
      for perm in permutations(flattened, r=len(flattened)):
           print(perm)
      >> ('a', 'b', 'c', 'd', 'e', 'f', 'g')
         ('a', 'b', 'c', 'd', 'e', 'g', 'f')
         ('a', 'b', 'c', 'd', 'f', 'e', 'g')
         ('a', 'b', 'c', 'd', 'f', 'g', 'e')
         ('a', 'b', 'c', 'd', 'g', 'e', 'f')
         ('a', 'b', 'c', 'd', 'g', 'f', 'e')
         ('a', 'b', 'c', 'e', 'd', 'f', 'g')
         ('a', 'b', 'c', 'e', 'd', 'g', 'f')
         ('a', 'b', 'c', 'e', 'f', 'd', 'g')
         ...
         ...
         ...
      

      【讨论】:

      • 在示例中 OP 没有
      • @Moberg 好吧,似乎在示例中 ad 始终是固定的,而 e, f, g 仅在彼此之间排列...
      【解决方案5】:
      from itertools import chain, permutations
      
      your_list = [[a], [b,c], [d], [e,f,g]]
      flattened = chain.from_iterable(your_list)
      perms = permutations(flattened)
      for perm in perms:
          print perm
      

      参考资料:

      【讨论】:

      • 这与@DeepSpace 的回答有何不同?
      • 我在输入这个时没有看到那个答案。
      • 像 DeepSpace 的回答一样,这 做 OP 要求的。
      猜你喜欢
      • 1970-01-01
      • 2020-03-30
      • 2012-12-03
      • 2013-11-18
      • 2013-09-10
      • 2010-10-29
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多