Chicony
Chicony

Reputation: 433

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

I have a list of lists containing unique strings and I want to produce an arbitrary number of different ways of sorting it. The list might look like the following:

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

The order of the lists need to be the same but I want to shuffle the ordering within a list and then have them in a single list, e.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]

What is a good pythonic way of achieving this? I'm on python 2.7.

Upvotes: 2

Views: 276

Answers (5)

PM 2Ring
PM 2Ring

Reputation: 55499

You can do this by taking the Cartesian product of the permutations of the sub-lists, and then flattening the resulting nested tuples.

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

output

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

If you need to do this in Python 2, you can replace the print line with this:

print list(chain.from_iterable(t))

Here's a more compact version, inspired by ewcz's answer:

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

Upvotes: 3

Michael Habeck
Michael Habeck

Reputation: 11

This might not be the most elegant solution, but I think it does what you want

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

Upvotes: 0

怀春춘
怀春춘

Reputation: 307

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

References:

Upvotes: -1

ewcz
ewcz

Reputation: 13097

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

produces:

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

Upvotes: 3

DeepSpace
DeepSpace

Reputation: 81684

You can flatten the list then simply generate its permutations:

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

Upvotes: -1

Related Questions