2011-11-23 17 views
5

我沒有找到一個更好的方式來標題中的這個問題。如果可以,請編輯。如何從Python中的二維列表中獲取所有可能的項目組合?

我有這樣一個列表的列表:

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

現在,我想那吐出這樣所有可能的組合功能:

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

哪裏也不表的數在預先已知的情況下,每個子列表的長度也不是預先知道的,但是所有出來的組合應該包含來自每個子列表的1個項目。

回答

11

您需要itertools.product()

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

任何人誰是想知道,在*中的前解包列表:http://stackoverflow.com/a/2921893/4549682 – wordsforthewise

0

這可能是什麼itertools.product()(其中斯文提到)作用:

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

這將工作,如果我總是隻有2子列表,如示例'[[1,2],['a','b']],然後你只需將這兩個子列表傳遞給這個函數,但事實並非如此,列表也可能是'[[ 'a','b','c'],[1,2],[{},[],()]]',所以現在我們有3個子列表,所以我們需要的是一個函數,乘以可變數目的列表。 – bigblind

+0

啊,我從你的例子中假設它總是成對的。那時我沒有更好的建議。 – Anko

0

下面是一個使用遞歸的解決方案,combs_raccum消化head(下一個列表在線)產生一個更胖的accum0,然後用tail(剩下的列表)和現在更胖的累積調用自己(「遞歸」)。

可能是內存繁重的用戶,因爲每次調用combs_r都會添加一個新的名稱空間,直到全部解除結束。 Python內部人員更有知識可能對此發表評論。

支付學習序言,恕我直言。

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) 
相關問題