รวมกันระหว่างสองรายการ?


187

ไม่นานมานี้และฉันมีปัญหาในการพันรอบอัลกอริทึมที่ฉันพยายามทำ โดยทั่วไปฉันมีสองรายการและต้องการรับชุดค่าผสมทั้งหมดของสองรายการ

ฉันอาจจะอธิบายไม่ถูกต้องดังนั้นนี่เป็นตัวอย่าง

name = 'a', 'b'
number = 1, 2

ผลลัพธ์ในกรณีนี้จะเป็น:

1.  A1 B2
2.  B1 A2

ส่วนที่ยุ่งยากคือฉันอาจมีรายการในตัวแปร“ ชื่อ” มากกว่ารายการในตัวแปร“ หมายเลข” (หมายเลขจะเท่ากับหรือน้อยกว่าตัวแปรชื่อเสมอ)

ฉันสับสนวิธีการรวมกันทั้งหมด (ซ้อนกันสำหรับวง?) และยิ่งสับสนในตรรกะเพื่อเลื่อนรายการในตัวแปรชื่อในกรณีที่มีรายการในชื่อมากกว่าพวกเขาอยู่ในรายการหมายเลข

ฉันไม่ใช่โปรแกรมเมอร์ที่ดีที่สุด แต่คิดว่าฉันจะให้มันยิงถ้ามีคนสามารถช่วยฉันชี้แจงตรรกะ / algoriythm เพื่อให้บรรลุนี้ ดังนั้นฉันเพิ่งจะติดอยู่บนที่ซ้อนกันสำหรับลูป

ปรับปรุง:

นี่คือผลลัพธ์ที่มี 3 ตัวแปรและตัวเลข 2 ตัว:

name = 'a', 'b', 'c'
number = 1, 2

เอาท์พุท:

1.  A1 B2
2.  B1 A2
3.  A1 C2
4.  C1 A2
5.  B1 C2
6.  C1 B2


1
@ dm03514 ฉันเห็นว่าและพบตัวอย่างสำหรับเป้าหมายที่ค่อนข้างคล้ายกันโดยใช้ itertools แต่ฉันกำลังสร้างต้นแบบใน python แต่จะเขียนโค้ดสุดท้ายเป็นภาษาอื่นดังนั้นฉันไม่ต้องการใช้เครื่องมือใด ๆ ที่ไม่เป็นประโยชน์
user1735075

1
สิ่งที่คุณขอไม่สมเหตุสมผลจริงๆ หากรายการแรกมี A, B, C และรายการที่สองมี 1,2 ผลลัพธ์ใดที่คุณคาดหวัง มันสามารถทำได้ถ้าตัวอย่างที่คุณให้มีผลลัพธ์ที่แตกต่างกัน 4 ตัวของหนึ่งตัวอักษรและหนึ่งหมายเลขแต่ละตัว (A1, A2, B1, B2) หรือถ้าทั้งสองรายการต้องมีขนาดเท่ากัน
ระหว่าง

1
ฉันเห็นด้วยกับ interjay โปรดระบุผลลัพธ์ในกรณีที่มีขนาดไม่เท่ากันมิฉะนั้นจะไม่สามารถให้โซลูชันทั่วไปได้
บาคุริจู

สวัสดีทุกคนฉันอัปเดตคำตอบเพื่อแสดงผลลัพธ์ด้วย 3 ชื่อและ 2 หมายเลข .. ฉันคิดว่าฉันอธิบายได้ดีไม่แน่ใจว่าทำไม downvote
user1735075

คำตอบ:


93

หมายเหตุ : คำตอบนี้สำหรับคำถามเฉพาะที่ถามข้างต้น หากคุณอยู่ที่นี่จาก Google และกำลังมองหาวิธีที่จะได้รับผลิตภัณฑ์คาร์ทีเซียนใน Python มิitertools.productฉะนั้นความเข้าใจในรายการง่ายๆอาจเป็นสิ่งที่คุณกำลังมองหา - ดูคำตอบอื่น ๆ


len(list1) >= len(list2)สมมติ แล้วสิ่งที่คุณดูเหมือนจะต้องการที่จะใช้พีชคณิตทั้งหมดของความยาวlen(list2)จากlist1และตรงกับพวกเขาด้วยรายการจาก List2 ในหลาม:

import itertools
list1=['a','b','c']
list2=[1,2]

[list(zip(x,list2)) for x in itertools.permutations(list1,len(list2))]

ผลตอบแทน

[[('a', 1), ('b', 2)], [('a', 1), ('c', 2)], [('b', 1), ('a', 2)], [('b', 1), ('c', 2)], [('c', 1), ('a', 2)], [('c', 1), ('b', 2)]]

1
ผลลัพธ์เป็นสิ่งที่ฉันต้องการ แต่เป็นไปได้หรือไม่ที่จะแบ่งปันตรรกะเบื้องหลังวิธีการทำ ถ้าฉันแปลงรหัสของฉันเป็น C หรือ Java ฉันจะไม่สามารถเข้าถึง zip หรือ itertools (แม้ว่าพวกเขาจะทำให้ชีวิตง่ายมาก)
user1735075

3
@ user1735075 ดูที่เอกสาร
sloth

1
@ user1735075: คุณรู้หรือไม่ว่า python นั้นเป็นโอเพนซอร์ซ? ดังนั้นคุณสามารถดาวน์โหลดแหล่งข้อมูลและดูว่าพวกเขาทำอะไร +1 ถึง Mr. Steak สำหรับชี้ให้เห็นว่าเอกสารจริงมีตัวอย่างการใช้งานที่ไม่ได้ใช้zipและคล้ายกัน
บาคุริจู

2
แท้จริงฉันไม่สามารถใช้งานมันได้แม้กับตัวอย่างของคุณ ... ทั้งหมดที่ฉันได้รับคือรายการของวัตถุซิป .. : |
m1nkeh

1
@logic ให้สิ่งที่ควรเป็นทางออกที่ยอมรับ
Bernhard Wagner

501

วิธีที่ง่ายที่สุดคือการใช้itertools.product:

a = ["foo", "melon"]
b = [True, False]
c = list(itertools.product(a, b))
>> [("foo", True), ("foo", False), ("melon", True), ("melon", False)]

11
OP ไม่ได้ขอผลิตภัณฑ์คาร์ทีเซียนและคำตอบนี้ (รวมถึงผลิตภัณฑ์อื่น ๆ ส่วนใหญ่) ไม่ได้ให้ผลลัพธ์ตามที่คาดหวังไว้ในคำถาม
ระหว่าง

17
@interjay คุณพูดถูก แต่คนจำนวนมากดูเหมือนจะหาคำตอบนี้ถูกต้องแล้วฉันก็แค่คิดว่าชื่อของคำถามนั้นไม่มีบริบท
xpy

3
@xpy ชื่อสั้นเกินไปที่จะอธิบายทุกอย่าง นั่นเป็นเหตุผลที่คุณต้องอ่านคำถามจริง
ระหว่าง

10
OP ต้องการการเปลี่ยนรูป แต่ Google ส่งคนที่มองหาชุดค่าผสม (เช่นฉัน) ให้กับคำตอบนี้ - ดีใจที่เห็นว่ามีคะแนนโหวต 8 เท่า!
Josh Friedlander

160

อาจง่ายกว่าที่ง่ายที่สุดด้านบน:

>>> a = ["foo", "bar"]
>>> b = [1, 2, 3]
>>> [(x,y) for x in a for y in b]  # for a list
[('foo', 1), ('foo', 2), ('foo', 3), ('bar', 1), ('bar', 2), ('bar', 3)]
>>> ((x,y) for x in a for y in b)  # for a generator if you worry about memory or time complexity.
<generator object <genexpr> at 0x1048de850>

โดยไม่ต้องนำเข้าใด ๆ


ทางออกที่ดีที่สุด! ขอบคุณ! การแก้ปัญหาอื่น ๆ ที่ผิดธรรมดาอย่างใดอย่างหนึ่งหรือที่ทำงานเฉพาะในกรณีที่เฉพาะเจาะจงเช่น> ข ฯลฯ
ฟิลิปป์ Schwarz

3
วิธีการแก้ปัญหา Pythonic มากที่สุด! (และหลีกเลี่ยงการนำเข้าที่ไม่จำเป็น)
Dalker

6
ความซับซ้อนของเวลาคือ O (n ^ 2)
Deepak Sharma

2
เดิมพันวิธีการแก้ปัญหา !! ความรู้เบื้องต้นแบบเปลือยเป็นวิธีที่ดีที่สุดเสมอ
Sabyasachi

22

ฉันกำลังมองหารายการคูณด้วยตัวเองด้วยชุดค่าผสมที่ไม่ซ้ำกันเท่านั้นซึ่งมีให้เป็นฟังก์ชั่นนี้

import itertools
itertools.combinations(list, n_times)

นี่เป็นข้อความที่ตัดตอนมาจากเอกสาร Python บน itertoolsที่อาจช่วยให้คุณค้นหาสิ่งที่คุณกำลังมองหา

Combinatoric generators:

Iterator                                 | Results
-----------------------------------------+----------------------------------------
product(p, q, ... [repeat=1])            | cartesian product, equivalent to a 
                                         |   nested for-loop
-----------------------------------------+----------------------------------------
permutations(p[, r])                     | r-length tuples, all possible 
                                         |   orderings, no repeated elements
-----------------------------------------+----------------------------------------
combinations(p, r)                       | r-length tuples, in sorted order, no 
                                         |   repeated elements
-----------------------------------------+----------------------------------------
combinations_with_replacement(p, r)      | r-length tuples, in sorted order, 
                                         | with repeated elements
-----------------------------------------+----------------------------------------
product('ABCD', repeat=2)                | AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
permutations('ABCD', 2)                  | AB AC AD BA BC BD CA CB CD DA DB DC
combinations('ABCD', 2)                  | AB AC AD BC BD CD
combinations_with_replacement('ABCD', 2) | AA AB AC AD BB BC BD CC CD DD

11

คุณอาจต้องการลองความเข้าใจในรายการบรรทัดเดียว:

>>> [name+number for name in 'ab' for number in '12']
['a1', 'a2', 'b1', 'b2']
>>> [name+number for name in 'abc' for number in '12']
['a1', 'a2', 'b1', 'b2', 'c1', 'c2']

11

วิธีที่ดีที่สุดในการค้นหาชุดค่าผสมทั้งหมดสำหรับรายการจำนวนมากคือ:

import itertools
from pprint import pprint

inputdata = [
    ['a', 'b', 'c'],
    ['d'],
    ['e', 'f'],
]
result = list(itertools.product(*inputdata))
pprint(result)

ผลลัพธ์จะเป็น:

[('a', 'd', 'e'),
 ('a', 'd', 'f'),
 ('b', 'd', 'e'),
 ('b', 'd', 'f'),
 ('c', 'd', 'e'),
 ('c', 'd', 'f')]

ขอบคุณคำตอบยอดเยี่ยม!
toinbis

10

หรือคำตอบของ KISS สำหรับรายการสั้น ๆ :

[(i, j) for i in list1 for j in list2]

ไม่ได้เป็นนักแสดงอย่าง itertools แต่คุณกำลังใช้ python ดังนั้นประสิทธิภาพจึงไม่ใช่ข้อกังวลอันดับต้น ๆ ของคุณ ...

ฉันชอบคำตอบอื่น ๆ ทั้งหมดเช่นกัน!


8

การปรับปรุงเล็กน้อยสำหรับคำตอบจาก interjay เพื่อให้ผลลัพธ์เป็นรายการที่เรียบ

>>> list3 = [zip(x,list2) for x in itertools.permutations(list1,len(list2))]
>>> import itertools
>>> chain = itertools.chain(*list3)
>>> list4 = list(chain)
[('a', 1), ('b', 2), ('a', 1), ('c', 2), ('b', 1), ('a', 2), ('b', 1), ('c', 2), ('c', 1), ('a', 2), ('c', 1), ('b', 2)]

อ้างอิงจากลิงค์นี้



4

ตอบคำถาม "ให้สองรายการค้นหาการเรียงสับเปลี่ยนที่เป็นไปได้ทั้งหมดของคู่หนึ่งรายการจากแต่ละรายการ" และใช้ฟังก์ชันการทำงานของ Python ขั้นพื้นฐาน (เช่นไม่มี itertools) และด้วยเหตุนี้ทำให้ง่ายต่อการทำซ้ำสำหรับภาษาโปรแกรมอื่น:

def rec(a, b, ll, size):
    ret = []
    for i,e in enumerate(a):
        for j,f in enumerate(b):
            l = [e+f]
            new_l = rec(a[i+1:], b[:j]+b[j+1:], ll, size)
            if not new_l:
                ret.append(l)
            for k in new_l:
                l_k = l + k
                ret.append(l_k)
                if len(l_k) == size:
                    ll.append(l_k)
    return ret

a = ['a','b','c']
b = ['1','2']
ll = []
rec(a,b,ll, min(len(a),len(b)))
print(ll)

ผลตอบแทน

[['a1', 'b2'], ['a1', 'c2'], ['a2', 'b1'], ['a2', 'c1'], ['b1', 'c2'], ['b2', 'c1']]

2

คำตอบที่ดีกว่านี้ใช้ได้กับความยาวของรายการที่ระบุเท่านั้น

นี่คือเวอร์ชันที่ใช้งานได้กับความยาวของอินพุต นอกจากนี้ยังทำให้ขั้นตอนวิธีชัดเจนในแง่ของแนวคิดทางคณิตศาสตร์ของการรวมกันและการเปลี่ยนแปลง

from itertools import combinations, permutations
list1 = ['1', '2']
list2 = ['A', 'B', 'C']

num_elements = min(len(list1), len(list2))
list1_combs = list(combinations(list1, num_elements))
list2_perms = list(permutations(list2, num_elements))
result = [
  tuple(zip(perm, comb))
  for comb in list1_combs
  for perm in list2_perms
]

for idx, ((l11, l12), (l21, l22)) in enumerate(result):
  print(f'{idx}: {l11}{l12} {l21}{l22}')

ผลลัพธ์นี้:

0: A1 B2
1: A1 C2
2: B1 A2
3: B1 C2
4: C1 A2
5: C1 B2
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.