Semua kombinasi daftar daftar


240

Saya pada dasarnya mencari versi python Combination ofList<List<int>>

Diberikan daftar daftar, saya membutuhkan daftar baru yang memberikan semua kemungkinan kombinasi item di antara daftar.

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

Jumlah daftar tidak diketahui, jadi saya perlu sesuatu yang berfungsi untuk semua kasus. Poin bonus untuk keanggunan!

Jawaban:


428

Anda membutuhkan 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
Bisakah seseorang menjelaskan arti tanda bintang *a?
Serrano

52
*aberarti ini adalah argumen yang diteruskan ke fungsi atau metode. def fn(a,b,c):akan menanggapi fn(*[1,2,3]) referensi
mjallday

1
@mjallday, mungkinkah menambahkan juga kombinasi ini: (7,4,1), (8,4,1), (9,4,1), (10,4,1), (7,5, 1), (8,5,1), (9,5,1), (10,5,1) dll?
Reman

1
@Reman Tidak sepenuhnya jelas apa yang ingin Anda dapatkan tetapi jika itu, misalnya, juga kebalikan dari masing-masing tuple, Anda dapat menggunakan fungsi pembungkus yang mengambil asebagai input, beralih dari itertools.product(*a)dan yieldke tuple yang diproduksi oleh itertoolsdan versi terbalik ( misalnya membuat daftar, reverse()dan mengubahnya kembali ke tuple). Terbaik ajukan pertanyaan baru.
Joachim Wagner

24

Solusi paling elegan adalah dengan menggunakan itertools.product di python 2.6.

Jika Anda tidak menggunakan Python 2.6, dokumen untuk itertools.product sebenarnya menunjukkan fungsi yang setara untuk melakukan produk dengan cara "manual":

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;

Saya harap Anda menemukan itu seanggun yang saya lakukan ketika saya pertama kali menemukannya.


5
Ada apa dengan titik koma itu? :)
Paolo Bergantino

3
Kekuatan kebiasaan. Saya suka bagaimana Python memungkinkan Anda menempatkan satu semi-colon, hanya untuk membantu kami programmer C / Java. Tapi jelas; sebenarnya bukan terminator pernyataan ketika Anda melakukan sesuatu seperti cetak ("foo") ;; yang sangat legal di C atau Java (meskipun tidak ada gunanya) tetapi dilarang dengan Python.
Matthew Flaschen

5

Numpy dapat melakukannya:

 >>> 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], ....]

Bisakah seseorang menjelaskan ini?
ashishv

5

Tidak ada yang salah dengan rekursi langsung untuk tugas ini, dan jika Anda membutuhkan versi yang dapat digunakan dengan string, ini mungkin sesuai dengan kebutuhan Anda:

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

Satu dapat menggunakan python dasar untuk ini. Kode membutuhkan fungsi untuk meratakan daftar daftar:

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

Maka seseorang dapat menjalankan:

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)

Keluaran:

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

Keluaran:

[('Akronim Merek: CBIQ', 'Merek Negara: DXB'),
('Akronim Merek: CBIQ', 'Merek Negara: BH'),
('Akronim Merek: KMEFIC', 'Merek Negara: DXB'),
( 'Merek Akronim: KMEFIC', 'Negara Merek: BH')]


Jawaban ini harus diterima, karena itu satu-satunya yang menggunakan fungsi bawaan, sambil menyoroti bahwa itu juga berfungsi untuk semua jenis heterogen.
pedjjj

Bagaimana jawaban ini berbeda dari yang diberikan bertahun-tahun yang lalu?
Dawid Laszuk
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.