2010-11-20 25 views
10

Mam listę takiego:permutacji listy list

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

Chcę wybrać element z każdej listy i połączyć je, aby być ciągiem.

Na przykład: 'aag aaa', '', '', 'AAR AAW ABG', '', '....' ABH

Jednak długość listy L, a długość każda wewnętrzna lista jest nieznana przed uruchomieniem programu. Więc jak mogę chcieć?

+2

Czy chcesz wszystkie kombinacje, czy losowe? – Thomas

+0

Wszystkie kombinacje – wong2

Odpowiedz

10

Weź zamiast tego previous solution i użyj itertools.product(*l).

+4

Aby przeliterować: '[" .join (s) dla s w itertools.product (* l)] ' –

+0

@ wong2 masz na myśli fantastyczny Mam nadzieję? Fantazja jest trochę inna :) – extraneon

+0

czy możesz wyjaśnić operatorowi *? Czuję, że nigdy 100% go nie dostałem. –

0

Dość łatwe itertools.product:

>>> import itertools 
>>> list(itertools.product("abc", "ab", "ghrw")) 
[('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')] 
5

Jeśli ktoś jest zainteresowany w algorytmie, oto bardzo prosty sposób korzystać z rekurencji znaleźć combo:

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

Tu idziesz

reduce(lambda a,b: [i+j for i in a for j in b], l) 

OUT: ['aag', 'aah', 'aar', 'aaw', 'abg', 'abh', 'abr', 'abw', 'bag', 'bah', 'bar', 'baw', 'bbg', 'bbh', 'bbr', 'bbw', 'cag', 'cah', 'car', 'caw', 'cbg', 'cbh', 'cbr', 'cbw'] 

Jeśli chcesz ponownie użyć/zregenerować:

def opOnCombos(a,b, op=operator.add): 
    return [op(i,j) for i in a for j in b] 

def f(x): 
    return lambda a,b: opOnCombo(a,b,x) 

reduce(opOnCombos, l) //same as before 
reduce(f(operator.mul), l)) //multiply combos of several integer list 
1

użyciem rekurencji

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

Piggy-odejściu od JasonWoof's answer. Poniżej zostanie utworzona lista zamiast drukowania. Należy pamiętać, że może to być bardzo powolne, ponieważ wymaga dużej ilości pamięci do przechowywania wartości.

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

Wynik

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

Poniżej jest odpowiednikiem substytucji itertools.product(*iterables[, repeat]):

Ta funkcja jest równoznaczne z następującym kodem, chyba, że ​​faktyczna realizacja nie budować wyniki pośrednie w pamięci:

def product(*args, **kwds): 
    pools = 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)