सूचियों की एक श्रृंखला का कार्टेशियन उत्पाद प्राप्त करें?


317

मैं कार्टेशियन उत्पाद (मूल्यों के हर संभव संयोजन) को सूचियों के समूह से कैसे प्राप्त कर सकता हूं?

इनपुट:

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]

वांछित उत्पादन:

[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), (2, 'a', 5) ...]

24
ध्यान रखें कि 'हर संभव संयोजन' 'कार्टेशियन उत्पाद' के समान नहीं है, क्योंकि कार्टेशियन उत्पादों में डुप्लिकेट की अनुमति है।
२०:३०

7
क्या कार्टेशियन उत्पाद का एक गैर डुप्लिकेट संस्करण है?
केजेडब्ल्यू

16
@KJW हाँ,set(cartesian product)
NoBugs

5
कार्टेशियन उत्पाद में कोई डुप्लिकेट नहीं होना चाहिए, जब तक कि इनपुट सूची में डुप्लिकेट स्वयं न हों। यदि आप कार्टेशियन उत्पाद में कोई डुप्लिकेट नहीं चाहते हैं, तो set(inputlist)अपनी सभी इनपुट सूचियों का उपयोग करें। परिणाम पर नहीं।
CamilB

@ ट्रिटिक क्या? कार्टेशियन उत्पाद की मानक परिभाषा एक सेट है। इतने सारे लोग अपवित्र क्यों होते हैं?
पास्कलीव

जवाबों:


378

itertools.product

पायथन 2.6 से उपलब्ध है।

import itertools

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]
for element in itertools.product(*somelists):
    print(element)

जो समान है,

for element in itertools.product([1, 2, 3], ['a', 'b'], [4, 5]):
    print(element)

22
यदि आप ओपी द्वारा प्रदान किए गए चर वेरिएबल का उपयोग करते हैं तो बस '*' वर्ण जोड़ना आवश्यक है।
ब्रायन बक

1
@ जस्का: परिणाम में तत्वों को product()उत्पन्न nitems_in_a_list ** nlistsकरता है ( reduce(mul, map(len, somelists)))। यह मानने का कोई कारण नहीं है कि किसी एकल तत्व की पैदावार O(nlists)(परिशोधन) नहीं है , अर्थात, समय की जटिलता सरल नेस्टेड- forलूप्स के लिए समान है, जैसे प्रश्न में इनपुट के लिए: nlists=3परिणाम में तत्वों की कुल संख्या:, 3*2*2और प्रत्येक तत्व में nlistsआइटम हैं ( 3इस मामले में)।
jfs

2
*सोमेलिस्ट से पहले का उपयोग क्या है ? यह क्या करता है?
विनीत कुमार दोषी

6
@VineetKumarDoshi: यहाँ यह फ़ंक्शन कॉल के लिए कई तर्कों में एक सूची को अनपैक करने के लिए उपयोग किया जाता है। यहाँ और पढ़ें: stackoverflow.com/questions/36901/…
Moberg

4
नोट: यह केवल तभी काम करता है जब प्रत्येक सूची में कम से कम एक आइटम हो
igo

84
import itertools
>>> for i in itertools.product([1,2,3],['a','b'],[4,5]):
...         print i
...
(1, 'a', 4)
(1, 'a', 5)
(1, 'b', 4)
(1, 'b', 5)
(2, 'a', 4)
(2, 'a', 5)
(2, 'b', 4)
(2, 'b', 5)
(3, 'a', 4)
(3, 'a', 5)
(3, 'b', 4)
(3, 'b', 5)
>>>

38

पायथन 2.5 और पुराने के लिए:

>>> [(a, b, c) for a in [1,2,3] for b in ['a','b'] for c in [4,5]]
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), 
 (2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5), 
 (3, 'b', 4), (3, 'b', 5)]

यहाँ product()(केवल एक चित्रण) का पुनरावर्ती संस्करण है :

def product(*args):
    if not args:
        return iter(((),)) # yield tuple()
    return (items + (item,) 
            for items in product(*args[:-1]) for item in args[-1])

उदाहरण:

>>> list(product([1,2,3], ['a','b'], [4,5])) 
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), 
 (2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5), 
 (3, 'b', 4), (3, 'b', 5)]
>>> list(product([1,2,3]))
[(1,), (2,), (3,)]
>>> list(product([]))
[]
>>> list(product())
[()]

पुनरावर्ती संस्करण काम नहीं करता है अगर कुछ पुनरावृत्तियों argsहैं।
21

20

itertools.product के साथ :

import itertools
result = list(itertools.product(*somelists))

6
*सोमेलिस्ट से पहले का उपयोग क्या है ?
विनीत कुमार दोषी

@VineetKumarDoshi "उत्पाद (somelists)" उप- कलाकारों के बीच एक कार्टेसियन उत्पाद है जो एक तत्व के रूप में पायथन को पहले "[1, 2, 3]" एक तत्व के रूप में मिलता है और फिर अगले कमन के बाद अन्य तत्व प्राप्त होता है और वह है पहला उत्पाद शब्द है ([1, 2, 3],), दूसरा ([4, 5],) और इसलिए "[([1, 2, 3]]), ([4, 5],), () [६, 7],]] " । यदि आप टुपल्स के अंदर तत्वों के बीच एक कार्टेशियन उत्पाद प्राप्त करना चाहते हैं, तो आपको ट्यूल संरचना के बारे में एस्टरिस्क के साथ पायथन को बताना होगा। शब्दकोश के लिए, आप ** का उपयोग करते हैं। अधिक यहाँ
hhh

19

मैं सूची बोध का उपयोग करूंगा:

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]

cart_prod = [(a,b,c) for a in somelists[0] for b in somelists[1] for c in somelists[2]]

1
मैं वास्तव में सूची समझ का उपयोग करके इस समाधान को पसंद करता हूं। मुझे नहीं पता कि अधिक क्यों नहीं उतारा जाता है, यह बहुत सरल है।
17:27 बजे llekn

20
@ ल्लेकन क्योंकि कोड को सूचियों की संख्या के अनुसार तय किया गया है
Bikng Rikimaru

11

यहां एक पुनरावर्ती जनरेटर है, जो किसी भी अस्थायी सूची को संग्रहीत नहीं करता है

def product(ar_list):
    if not ar_list:
        yield ()
    else:
        for a in ar_list[0]:
            for prod in product(ar_list[1:]):
                yield (a,)+prod

print list(product([[1,2],[3,4],[5,6]]))

आउटपुट:

[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]

1
वे स्टैक में संग्रहीत हैं, हालांकि।
क्वेंटिन प्रदेट

@QuentinPradet का क्या मतलब है कि जैसे एक जनरेटर def f(): while True: yield 1अपने स्टैक के आकार को बढ़ाता रहेगा जैसा कि हम इसके माध्यम से जाते हैं?
अनुराग उनियाल

@QuentinPradet हाँ, लेकिन इस मामले में भी केवल अधिकतम गहराई के लिए आवश्यक ढेर, पूरी सूची नहीं है, इसलिए इस मामले में 3 का ढेर
अनुराग उनियाल

यह सच है, क्षमा करें। एक बेंचमार्क दिलचस्प हो सकता है। :)
क्वेंटिन Pradet

11

पायथन 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)

दोनों का परिणाम एक पुनरावृत्ति है, इसलिए यदि आपको आगे की प्रक्रिया के लिए एक सूची की आवश्यकता है, तो उपयोग करें list(result)


प्रलेखन के अनुसार, वास्तविक itertools.product कार्यान्वयन मध्यवर्ती परिणाम नहीं बनाता है, जो महंगा हो सकता है। मध्यम आकार की सूचियों के लिए इस तकनीक का उपयोग करना बहुत जल्दी हाथ से निकल सकता है।
त्रिफलक

4
मैं ओपी को केवल दस्तावेज के लिए इंगित कर सकता हूं, उसे उसके लिए नहीं पढ़ सकता हूं।

1
प्रलेखन से कोड का मतलब यह दिखाना है कि उत्पाद फ़ंक्शन क्या करता है, पायथन के पुराने संस्करणों के लिए वर्कअराउंड के रूप में नहीं।
त्रिपिटक

9

हालाँकि पहले से ही कई उत्तर हैं, मैं अपने कुछ विचार साझा करना चाहूंगा:

Iterative दृष्टिकोण

def cartesian_iterative(pools):
  result = [[]]
  for pool in pools:
    result = [x+[y] for x in result for y in pool]
  return result

पुनरावर्ती दृष्टिकोण

def cartesian_recursive(pools):
  if len(pools) > 2:
    pools[0] = product(pools[0], pools[1])
    del pools[1]
    return cartesian_recursive(pools)
  else:
    pools[0] = product(pools[0], pools[1])
    del pools[1]
    return pools
def product(x, y):
  return [xx + [yy] if isinstance(xx, list) else [xx] + [yy] for xx in x for yy in y]

लैम्ब्डा दृष्टिकोण

def cartesian_reduct(pools):
  return reduce(lambda x,y: product(x,y) , pools)

"इटरेटिव एप्रोच" में, परिणाम को परिणाम के रूप में क्यों घोषित किया जाता है = [[]] मुझे पता है कि यह list_of_list है, लेकिन सामान्य तौर पर भले ही हम list_of_list घोषित करते हैं हम [] का उपयोग करते हैं और [[]]
सचिन एस

मैं पायथोनिक समाधानों के मामले में थोड़ा नया हूं। क्या आप या कुछ राहगीर कृपया अलग-अलग छोरों में "पुनरावृति दृष्टिकोण" में समझ की सूची लिखेंगे?
जॉनी बॉय

4

पुनरावर्ती दृष्टिकोण:

def rec_cart(start, array, partial, results):
  if len(partial) == len(array):
    results.append(partial)
    return 

  for element in array[start]:
    rec_cart(start+1, array, partial+[element], results)

rec_res = []
some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]  
rec_cart(0, some_lists, [], rec_res)
print(rec_res)

निष्क्रिय दृष्टिकोण:

def itr_cart(array):
  results = [[]]
  for i in range(len(array)):
    temp = []
    for res in results:
      for element in array[i]:
        temp.append(res+[element])
    results = temp

  return results

some_lists = [[1, 2, 3], ['a', 'b'], [4, 5]]  
itr_res = itr_cart(some_lists)
print(itr_res)

3

वरदा स्वाद में उपरोक्त पुनरावर्ती जनरेटर समाधान के लिए एक मामूली संशोधन:

def product_args(*args):
    if args:
        for a in args[0]:
            for prod in product_args(*args[1:]) if args[1:] else ((),):
                yield (a,) + prod

और निश्चित रूप से एक आवरण जो इसे उस समाधान के समान काम करता है:

def product2(ar_list):
    """
    >>> list(product(()))
    [()]
    >>> list(product2(()))
    []
    """
    return product_args(*ar_list)

साथ एक व्यापार बंद : यह जांच करता है कि प्रत्यावर्तन प्रत्येक बाहरी पाश पर तोड़ना चाहिए, और एक लाभ : खाली कॉल पर कोई उपज है, जैसे product(()), जो मुझे लगता है कि अर्थ की दृष्टि से अधिक सही होगा (doctest देखें)।

सूची की समझ के बारे में: गणितीय परिभाषा एक मनमानी संख्या में तर्कों पर लागू होती है, जबकि सूची की समझ केवल उनमें से एक ज्ञात संख्या से निपट सकती है।


2

बस जो पहले से ही कहा गया है, उसमें थोड़ा सा जोड़ने के लिए: यदि आप सिम्पी का उपयोग करते हैं, तो आप तार के बजाय प्रतीकों का उपयोग कर सकते हैं जो उन्हें गणितीय रूप से उपयोगी बनाता है।

import itertools
import sympy

x, y = sympy.symbols('x y')

somelist = [[x,y], [1,2,3], [4,5]]
somelist2 = [[1,2], [1,2,3], [4,5]]

for element in itertools.product(*somelist):
  print element

सिम्पी के बारे में ।



0

स्टोनहेंज दृष्टिकोण:

def giveAllLists(a, t):
    if (t + 1 == len(a)):
        x = []
        for i in a[t]:
            p = [i]
            x.append(p)
        return x
    x = []

    out = giveAllLists(a, t + 1)
    for i in a[t]:

        for j in range(len(out)):
            p = [i]
            for oz in out[j]:
                p.append(oz)
            x.append(p)
    return x

xx= [[1,2,3],[22,34,'se'],['k']]
print(giveAllLists(xx, 0))

उत्पादन:

[[1, 22, 'k'], [1, 34, 'k'], [1, 'se', 'k'], [2, 22, 'k'], [2, 34, 'k'], [2, 'se', 'k'], [3, 22, 'k'], [3, 34, 'k'], [3, 'se', 'k']]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.