是否有一种 pythonic 方式来排列列表列表?

Is there a pythonic way of permuting a list of list?

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

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.

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

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

参考文献:

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

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))

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

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))