2011-11-23 8 views
5

Nie znalazłem lepszego sposobu na wyrażenie tego pytania w tytule. Jeśli możesz, edytuj.Jak uzyskać wszystkie możliwe kombinacje elementów z 2-wymiarowej listy w python?

Mam listę list tak:

a = [['a','b'],[1,2]] 

teraz chciałbym funkcję, która wyrzuca z siebie wszelką możliwą kombinację takiego:

[['a',1],['a',2],['b',1],['b',2]] 

gdzie ani liczby list in a jest znane z wyprzedzeniem, ani też nie jest znana długość każdej z podanych list podrzędnych, ale wszystkie kombinacje, które wyjdą, powinny zawierać 1 element z każdej podlisty.

Odpowiedz

11

Trzeba itertools.product():

>>> list(itertools.product(*a)) 
[('a', 1), ('a', 2), ('b', 1), ('b', 2)] 
+0

Dla każdego, kto zastanawia się, w * przed rozpakowuje listę: http://stackoverflow.com/a/2921893/4549682 – wordsforthewise

0

To może być co itertools.product() (który wspomina Sven) robi:

def combs(list1, list2): 
    results = [] 
    for x in list1: 
     for y in list2: 
      l.append([x,y]) 
    return results 
+0

To będzie działać, jeśli zawsze tylko 2 list podrzędnych jak w przykładzie '[[1,2], ['a', 'b']], a następnie wystarczy przekazać dwie listy podrzędne do tej funkcji, ale tak nie jest, lista mogłaby równie dobrze wyglądać następująco: [[ 'a', 'b', 'c'], [1,2], [{}, [],()]] ', więc teraz mamy 3 podlisty, więc potrzebujemy funkcji, w której pomnóż zmienną liczbę list. – bigblind

+0

Ah, założyłem z twojego przykładu, że zawsze będą to pary. Nie mam wtedy lepszej sugestii. – Anko

0

Oto rozwiązanie przy użyciu rekursji, combs_r ma accum strawienia head (następna lista w linii), aby wytworzyć grubszy accum0, następnie wywołuje się ("rekursja") z tail (pozostałe listy) i teraz grubszym akumulatorem accum0.

Może być ciężkim użytkownikiem pamięci, ponieważ każde wywołanie do combs_r dodaje nową przestrzeń nazw, aż do końca, gdy wszystko się rozwinie. Osoba bardziej kompetentna w interpreterze Pythona może komentować to.

Płaci, aby dowiedzieć się prolog, IMHO.

def combs(ll): 
    if len(ll) == 0: 
     return [] 
    if len(ll) == 1: 
     return [[item] for item in ll[0]] 
    elif len(ll) == 2: 
     return lmul(ll[0], [[item] for item in ll[1]]) 
    else: 
     return combs_r(ll[1:], ll[0]) 

def combs_r(ll, accum): 
    head = ll[0] 
    tail = ll[1:] 
    accum0 = [] 
    accum0 = lmul(head, accum) 
    if len(tail) == 0: 
     return accum0 
    else: 
     return combs_r(tail, accum0) 

def lmul(head, accum): 
    accum0 = [] 
    for ah in head: 
     for cc in accum: 
      #cc will be reused for each ah, so make a clone to mutate 
      cc0 = [x for x in cc] 
      cc0.append(ah) 
      accum0.append(cc0) 
    return accum0 

sampleip = [['a','b','c'],[1,2], ['A', 'B']] 
sampleip2 = [['a','b','c'],[1,2]] 
sampleip1 = [['a','b','c']] 
sampleip0 = [] 
print combs(sampleip0) 
print combs(sampleip1) 
print combs(sampleip2) 
print combs(sampleip) 
Powiązane problemy