การรวมกันทั้งหมดของรายการของรายการ


240

โดยทั่วไปฉันกำลังมองหาชุดการรวมกันของหลามList<List<int>>

รับรายการของรายการฉันต้องการรายการใหม่ที่ให้ชุดค่าผสมที่เป็นไปได้ทั้งหมดของรายการระหว่างรายการ

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

จำนวนรายการไม่เป็นที่รู้จักดังนั้นฉันต้องการบางสิ่งที่เหมาะกับทุกกรณี คะแนนโบนัสเพื่อความสง่างาม!

คำตอบ:


428

คุณต้องการ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
ใครช่วยอธิบายความหมายของเครื่องหมายดอกจันได้*aบ้าง
Serrano

52
*aหมายความว่าสิ่งเหล่านี้เป็นข้อโต้แย้งที่ถูกส่งผ่านไปยังฟังก์ชั่นหรือวิธีการ def fn(a,b,c):จะตอบสนองต่อการfn(*[1,2,3]) อ้างอิง
mjallday

1
@mjallday เป็นไปได้หรือไม่ที่จะเพิ่มชุดค่าผสมเหล่านี้: (7,4,1), (8,4,1), (9,4,1), (10,4,1), (7,5, 1), (8,5,1), (9,5,1), (10,5,1) เป็นต้น?
Reman

1
@Reman มันไม่ได้ชัดเจนว่าคุณต้องการได้อะไร แต่ถ้ามันเป็นเช่นนั้นสิ่งที่ตรงกันข้ามของ tuple แต่ละตัวคุณสามารถใช้ฟังก์ชั่น aa wrapper ที่ทำหน้าที่aเป็นอินพุตมันวนซ้ำitertools.product(*a)และyieldทั้ง tuple ที่สร้างโดยitertoolsและเวอร์ชันย้อนกลับ ( เช่นสร้างรายการreverse()มันและแปลงกลับเป็น tuple) ถามคำถามใหม่ที่ดีที่สุด
Joachim Wagner

24

ทางออกที่ดีที่สุดคือใช้itertools.productใน python 2.6

หากคุณไม่ได้ใช้ Python 2.6 เอกสารสำหรับ itertools.product แสดงฟังก์ชันที่เทียบเท่าเพื่อทำผลิตภัณฑ์ด้วยวิธี "ด้วยตนเอง":

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;

ฉันหวังว่าคุณจะพบว่าสง่างามอย่างที่ฉันทำเมื่อฉันพบมันครั้งแรก


5
เกิดอะไรขึ้นกับอัฒภาคนั้น? :)
เปาโล Bergantino

3
พลังแห่งนิสัย ฉันชอบที่ Python ช่วยให้คุณใส่เซมิโคลอนเพียงอันเดียวเพื่อช่วยโปรแกรมเมอร์ของเรา แต่มันชัดเจน ไม่ได้เป็น terminator ของ statement จริงๆเมื่อคุณทำสิ่งต่าง ๆ เช่น print ("foo") ;; ซึ่งถูกกฎหมายอย่างสมบูรณ์ใน C หรือ Java (แม้ว่าไม่มีจุดหมาย) แต่ห้ามใน Python
Matthew Flaschen

5

Numpy สามารถทำได้:

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

มีคนอธิบายเรื่องนี้ได้ไหม
ashishv

5

ไม่มีอะไรผิดปกติกับการเรียกซ้ำตรงๆสำหรับงานนี้และหากคุณต้องการรุ่นที่ใช้งานได้กับสตริงสิ่งนี้อาจเหมาะกับความต้องการของคุณ:

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

หนึ่งสามารถใช้ฐานหลามนี้ รหัสต้องการฟังก์ชั่นเพื่อทำให้รายการของรายการเรียบขึ้น:

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

จากนั้นหนึ่งสามารถเรียกใช้:

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)

เอาท์พุท:

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

เอาท์พุท:

[('ตัวย่อยี่ห้อ: CBIQ', 'ยี่ห้อประเทศ: DXB'),
('ตัวย่อยี่ห้อ: CBIQ', 'ยี่ห้อประเทศ: BH'),
('ตัวย่อยี่ห้อ: KMEFIC', 'ยี่ห้อประเทศ: DXB'),
( 'ตัวย่อยี่ห้อ: KMEFIC', 'ยี่ห้อประเทศ: BH')]


คำตอบนี้ควรได้รับการยอมรับเนื่องจากเป็นคำเดียวที่ใช้ฟังก์ชั่นในตัวขณะที่เน้นว่ามันใช้ได้กับทุกประเภทและหลากหลาย
pedjjj

คำตอบนี้ต่างจากคำตอบที่ให้เมื่อหลายปีก่อนอย่างไร?
Dawid Laszuk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.