Tất cả sự kết hợp của một danh sách các danh sách


240

Về cơ bản, tôi đang tìm kiếm một phiên bản kết hợp của pythonList<List<int>>

Đưa ra một danh sách các danh sách, tôi cần một danh sách mới cung cấp tất cả các kết hợp các mục có thể có giữa các danh sách.

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

Số lượng danh sách là không xác định, vì vậy tôi cần một cái gì đó hoạt động cho tất cả các trường hợp. Điểm thưởng cho sự thanh lịch!

Câu trả lời:


428

bạn cần 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
Ai đó có thể giải thích ý nghĩa của dấu hoa thị trong *a?
Serrano

52
*acó nghĩa đây là các đối số được truyền cho hàm hoặc phương thức. def fn(a,b,c):sẽ trả lời fn(*[1,2,3]) tham khảo
mjallday

1
@mjallday, có thể thêm các kết hợp này không: (7,4,1), (8.4,1), (9,4,1), (10,4,1), (7,5, 1), (8,5,1), (9,5,1), (10,5,1) v.v?
Reman

1
@Reman Nó không hoàn toàn rõ ràng những gì bạn muốn nhận được nhưng nếu nó là, ví dụ, cũng là ngược lại của mỗi tuple bạn có thể sử dụng aa chức năng wrapper mà mất anhư là đầu vào, lặp qua itertools.product(*a)yieldlà cả tuple sản xuất bởi itertoolsvà một phiên bản ngược ( ví dụ: tạo một danh sách, reverse()nó và chuyển đổi trở lại tuple). Tốt nhất hãy hỏi một câu hỏi mới.
Joachim Wagner

24

Giải pháp tao nhã nhất là sử dụng itertools.product trong python 2.6.

Nếu bạn không sử dụng Python 2.6, các tài liệu cho itertools.product thực sự hiển thị một chức năng tương đương để thực hiện sản phẩm theo cách "thủ công":

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;

Tôi hy vọng bạn thấy rằng nó thanh lịch như tôi đã làm khi tôi gặp nó lần đầu tiên.


5
Có chuyện gì với dấu chấm phẩy đó? :)
Paolo Bergantino

3
Thói quen của lực lượng. Tôi thích cách Python cho phép bạn đặt một dấu chấm phẩy, chỉ để giúp chúng tôi lập trình viên C / Java. Nhưng nó rõ ràng; không thực sự là một dấu kết thúc câu lệnh khi bạn làm một cái gì đó như in ("foo") ;; đó là hoàn toàn hợp pháp trong C hoặc Java (mặc dù vô nghĩa) nhưng bị cấm trong Python.
Matthew Flaschen

5

Numpy có thể làm điều đó:

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

Ai đó có thể giải thích điều này?
ashishv

5

Không có gì sai khi đệ quy thẳng cho nhiệm vụ này và nếu bạn cần một phiên bản hoạt động với chuỗi, điều này có thể phù hợp với nhu cầu của bạn:

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

Người ta có thể sử dụng python cơ sở cho việc này. Mã cần một hàm để làm phẳng danh sách các danh sách:

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

Sau đó, một người có thể chạy:

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)

Đầu ra:

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

Đầu ra:

[( 'Nhãn hiệu viết tắt: CBIQ', 'Thương hiệu Quốc gia: DXB'),
( 'Nhãn hiệu viết tắt: CBIQ', 'Thương hiệu Quốc gia: BH'),
( 'Nhãn hiệu viết tắt: KMEFIC', 'Thương hiệu Quốc gia: DXB'),
( Ac Từ viết tắt thương hiệu: KMEFIC ',' Quốc gia thương hiệu: BH ')]


Câu trả lời này phải được chấp nhận, vì đây là câu duy nhất sử dụng hàm tích hợp, trong khi nhấn mạnh rằng nó cũng hoạt động cho bất kỳ loại nào và cả các loại không đồng nhất.
pedjjj

Làm thế nào là câu trả lời này khác với câu trả lời nhiều năm trước?
Dawid Laszuk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.