Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Permutations of a list of lists

Tags:

I have a list like this:

l = [['a', 'b', 'c'], ['a', 'b'], ['g', 'h', 'r', 'w']]

I want to pick an element from each list and combine them to be a string.

For example: 'aag', 'aah', 'aar', 'aaw', 'abg', 'abh' ....

However, the length of the list l and the length of each inner list are all unknown before the program is running. So how can I do want I want?

like image 410
wong2 Avatar asked Nov 20 '10 16:11

wong2


People also ask

How do you find all permutations in a list?

The number of permutations on a set of n elements is given by n!. For example, there are 2! = 2*1 = 2 permutations of {1, 2}, namely {1, 2} and {2, 1}, and 3! = 3*2*1 = 6 permutations of {1, 2, 3}, namely {1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, {3, 1, 2} and {3, 2, 1}.

Can you have a list of list of lists in Python?

Python provides an option of creating a list within a list. If put simply, it is a nested list but with one or more lists inside as an element. Here, [a,b], [c,d], and [e,f] are separate lists which are passed as elements to make a new list. This is a list of lists.

How do you get all the combinations of two lists in Python?

The unique combination of two lists in Python can be formed by pairing each element of the first list with the elements of the second list. Method 1 : Using permutation() of itertools package and zip() function. Approach : Import itertools package and initialize list_1 and list_2.


4 Answers

Take a previous solution and use itertools.product(*l) instead.

like image 101
Ignacio Vazquez-Abrams Avatar answered Sep 20 '22 15:09

Ignacio Vazquez-Abrams


If anybody's interested in the algorithm, here's a very simple way to use recursion to find the combos:

 l = [['a', 'b', 'c'], ['a', 'b'], ['g', 'h', 'r', 'w']]
 def permu(lists, prefix=''):
      if not lists:
           print prefix
           return
      first = lists[0]
      rest = lists[1:]
      for letter in first:
           permu(rest, prefix + letter)
 permu(l)
like image 32
JasonWoof Avatar answered Sep 24 '22 15:09

JasonWoof


using recursion

def permutenew(l):
if len(l)==1:
    return l[0]
else:   
    lnew=[]
    for a in l[0]:
        for b in permutenew(l[1:]):
            lnew.append(a+b)
    return lnew

l = [['a', 'b', 'c'], ['a', 'b'], ['g', 'h', 'r', 'w']]
print permutenew(l)
like image 41
db42 Avatar answered Sep 23 '22 15:09

db42


Piggy-backing off of JasonWoof's answer. The following will create a list instead of printing. Be mindful that this may be very slow as it requires a lot of memory to store the values.

from __future__ import print_function
import itertools # Not actually used in the code below

def permu(lists):
    def fn(lists, group=[], result=[]):
        if not lists:
            result.append(group)
            return
        first, rest = lists[0], lists[1:]
        for letter in first:
            fn(rest, group + [letter], result)
    result = []
    fn(lists, result=result)
    return result

if __name__ == '__main__':
    ll = [ [[1, 2, 3], [5, 10], [42]],
           [['a', 'b', 'c'], ['a', 'b'], ['g', 'h', 'r', 'w']] ]
    nth = lambda i: 'Permutation #{0}:\n{1}'.format(i, '-'*16)

    # Note: permu(list) can be replaced with itertools.product(*l)
    [[print(p) for p in [nth(i)]+permu(l)+['\n']] for i,l in enumerate(ll)]

Result

Permutation #0:
----------------
[1, 5, 42]
[1, 10, 42]
[2, 5, 42]
[2, 10, 42]
[3, 5, 42]
[3, 10, 42]


Permutation #1:
----------------
['a', 'a', 'g']
['a', 'a', 'h']
['a', 'a', 'r']
['a', 'a', 'w']
['a', 'b', 'g']
['a', 'b', 'h']
['a', 'b', 'r']
['a', 'b', 'w']
['b', 'a', 'g']
['b', 'a', 'h']
['b', 'a', 'r']
['b', 'a', 'w']
['b', 'b', 'g']
['b', 'b', 'h']
['b', 'b', 'r']
['b', 'b', 'w']
['c', 'a', 'g']
['c', 'a', 'h']
['c', 'a', 'r']
['c', 'a', 'w']
['c', 'b', 'g']
['c', 'b', 'h']
['c', 'b', 'r']
['c', 'b', 'w']

Below is an equivalent substitution for itertools.product(*iterables[, repeat]):

This function is equivalent to the following code, except that the actual implementation does not build up intermediate results in memory:

def product(*args, **kwds):
    pools = list(map(tuple, args)) * kwds.get('repeat', 1)
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)
like image 44
Mr. Polywhirl Avatar answered Sep 22 '22 15:09

Mr. Polywhirl