2009-04-28 31 views
137

tôi về cơ bản tìm kiếm một phiên bản python của Combination of List<List<int>>Tất cả sự kết hợp của một danh sách liệt kê

Cho một danh sách liệt kê, tôi cần một danh sách mới cung cấp cho tất cả các kết hợp có thể có của các mụ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ố danh sách không xác định, vì vậy tôi cần một số thứ hoạt động cho mọi trường hợp. Điểm thưởng cho sự sang trọng!

Trả lời

266

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)] 
+10

Could ai đó giải thích ý nghĩa của dấu sao trong '* a'? – Serrano

+23

'* a' có nghĩa là những đối số này được chuyển đến hàm hoặc phương thức. 'def fn (a, b, c):' sẽ trả về 'fn (* [1,2,3])' [tham chiếu] (http://www.saltycrane.com/blog/2008/01/how- to-use-args-và-kwargs-in-python /) – mjallday

+1

@mjallday, có thể thêm các kết hợp sau: (7,4,1), (8,4,1), (9,4, 1), (10,4,1), (7,5,1), (8,5,1), (9,5,1), (10,5,1) vv? – Reman

23

Giải pháp thanh lịch 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 hiện một chức năng tương đương để làm sản phẩm "bằng tay" cách:

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) 
+0

Tôi đang sử dụng 2.6 ngay bây giờ, nhưng cảm ơn thông tin! – Lin

14
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 như thanh lịch như tôi đã làm khi tôi lần đầu tiên gặp phải nó.

+2

Có gì với dấu chấm phẩy đó? :) –

+3

Lực lượng của thói quen. 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 ol. Nhưng rõ ràng; không thực sự là một terminator tuyên bố 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. –

2

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

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

0

Không có gì sai với đệ quy thẳng lên cho nhiệm vụ này, và nếu bạn cần một phiên bản làm việc 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'] 
Các vấn đề liên quan