Liste listesinin tüm kombinasyonları


240

Temelde Kombinasyonun bir python sürümünü arıyorumList<List<int>>

Bir liste listesi verildiğinde, listeler arasındaki tüm olası öğe kombinasyonlarını veren yeni bir listeye ihtiyacım var.

[[1,2,3],[4,5,6],[7,8,9,10]] -> [[1,4,7],[1,4,8],...,[3,6,10]]

Liste sayısı bilinmiyor, bu yüzden tüm durumlar için çalışan bir şeye ihtiyacım var. Zarafet için bonus puan!

Yanıtlar:


428

ihtiyacınız itertools.product:

>>> import itertools
>>> a = [[1,2,3],[4,5,6],[7,8,9,10]]
>>> list(itertools.product(*a))
[(1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 4, 10), (1, 5, 7), (1, 5, 8), (1, 5, 9), (1, 5, 10), (1, 6, 7), (1, 6, 8), (1, 6, 9), (1, 6, 10), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 4, 10), (2, 5, 7), (2, 5, 8), (2, 5, 9), (2, 5, 10), (2, 6, 7), (2, 6, 8), (2, 6, 9), (2, 6, 10), (3, 4, 7), (3, 4, 8), (3, 4, 9), (3, 4, 10), (3, 5, 7), (3, 5, 8), (3, 5, 9), (3, 5, 10), (3, 6, 7), (3, 6, 8), (3, 6, 9), (3, 6, 10)]

20
Birisi yıldız işaretinin anlamını açıklayabilir *ami?
Serrano

52
*abunlar işleve veya yönteme iletilen bağımsız değişkenlerdir. referansadef fn(a,b,c): cevap verirfn(*[1,2,3])
mjallday

1
@mjallday, şu kombinasyonları da eklemek mümkün müdür: (7,4,1), (8,4,1), (9,4,1), (10,4,1), (7,5, 1), (8,5,1), (9,5,1), (10,5,1) vb.
Reman

1
Tamamen almak istediğini açık değil ancak sorun olduğu takdirde, örneğin, aynı zamanda her başlığın ters sen alır aa sarmalayıcı işlevini kullanabilirsiniz @Reman agirdi olarak, üzerinde dolaşır itertools.product(*a)ve yieldürettiği tuple ikisi s itertoolsve ters sürümü ( örneğin, bir liste oluşturun ve bu listeye reverse()dönüştürün). En iyisi yeni bir soru sor.
Joachim Wagner

24

En zarif çözüm itertools.product'u python 2.6'da kullanmaktır .

Python 2.6 kullanmıyorsanız, itertools.product belgeleri aslında ürünü "manuel" şekilde yapmak için eşdeğer bir işlev gösterir:

def product(*args, **kwds):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    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)

19
listOLists = [[1,2,3],[4,5,6],[7,8,9,10]]
for list in itertools.product(*listOLists):
  print list;

Umarım ilk karşılaştığım kadar zarif bulursunuz.


5
O noktalı virgülün nesi var? :)
Paolo Bergantino

3
Alışkanlık gücü. Python'un C / Java programcılarına yardımcı olmamıza yardımcı olmak için bir noktalı virgül koymanıza nasıl izin verdiğini seviyorum. Ama açıktır; print ("foo") gibi bir şey yaptığınızda gerçekten bir deyim sonlandırıcı değildir ;; C veya Java için mükemmel yasaldır (anlamsız da olsa), ancak Python'da yasaklanmıştır.
Matthew Flaschen

5

Numpy yapabilir:

 >>> import numpy
 >>> a = [[1,2,3],[4,5,6],[7,8,9,10]]
 >>> [list(x) for x in numpy.array(numpy.meshgrid(*a)).T.reshape(-1,len(a))]
[[ 1, 4, 7], [1, 5, 7], [1, 6, 7], ....]

Birisi bunu açıklayabilir mi?
ashishv

5

Bu görev için doğrudan özyineleme ile yanlış bir şey yoktur ve dizelerle çalışan bir sürüme ihtiyacınız varsa, bu ihtiyaçlarınızı karşılayabilir:

combinations = []

def combine(terms, accum):
    last = (len(terms) == 1)
    n = len(terms[0])
    for i in range(n):
        item = accum + terms[0][i]
        if last:
            combinations.append(item)
        else:
            combine(terms[1:], item)


>>> a = [['ab','cd','ef'],['12','34','56']]
>>> combine(a, '')
>>> print(combinations)
['ab12', 'ab34', 'ab56', 'cd12', 'cd34', 'cd56', 'ef12', 'ef34', 'ef56']

3

Bunun için temel python kullanılabilir. Kod, liste listelerini düzleştirmek için bir işleve ihtiyaç duyar:

def flatten(B):    # function needed for code below;
    A = []
    for i in B:
        if type(i) == list: A.extend(i)
        else: A.append(i)
    return A

Sonra biri çalıştırabilir:

L = [[1,2,3],[4,5,6],[7,8,9,10]]

outlist =[]; templist =[[]]
for sublist in L:
    outlist = templist; templist = [[]]
    for sitem in sublist:
        for oitem in outlist:
            newitem = [oitem]
            if newitem == [[]]: newitem = [sitem]
            else: newitem = [newitem[0], sitem]
            templist.append(flatten(newitem))

outlist = list(filter(lambda x: len(x)==len(L), templist))  # remove some partial lists that also creep in;
print(outlist)

Çıktı:

[[1, 4, 7], [2, 4, 7], [3, 4, 7], 
[1, 5, 7], [2, 5, 7], [3, 5, 7], 
[1, 6, 7], [2, 6, 7], [3, 6, 7], 
[1, 4, 8], [2, 4, 8], [3, 4, 8], 
[1, 5, 8], [2, 5, 8], [3, 5, 8], 
[1, 6, 8], [2, 6, 8], [3, 6, 8], 
[1, 4, 9], [2, 4, 9], [3, 4, 9], 
[1, 5, 9], [2, 5, 9], [3, 5, 9], 
[1, 6, 9], [2, 6, 9], [3, 6, 9], 
[1, 4, 10], [2, 4, 10], [3, 4, 10], 
[1, 5, 10], [2, 5, 10], [3, 5, 10], 
[1, 6, 10], [2, 6, 10], [3, 6, 10]]

-1
from itertools import product 
list_vals = [['Brand Acronym:CBIQ', 'Brand Acronym :KMEFIC'],['Brand Country:DXB','Brand Country:BH']]
list(product(*list_vals))

Çıktı:

[('Marka Kısaltma: CBIQ', 'Marka Ülke: DXB'),
('Marka Kısaltma: CBIQ', 'Marka Ülke: BH'),
('Marka Kısaltma: KMEFIC', 'Marka Ülke: DXB'),
( 'Marka Kısaltması: KMEFIC', 'Marka Ülke: BH')]


Bu cevap kabul edilmelidir, çünkü yerleşik bir işlev kullanan tek yanıttır, aynı zamanda herhangi bir ve aynı zamanda heterojen tipler için de çalıştığını vurgular.
pedjjj

Bu cevap yıllar önce verilen cevaptan nasıl farklı?
Dawid Laszuk
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.