किसी सूची के तत्वों के सभी संभव संयोजन कैसे प्राप्त करें?


422

मेरे पास 15 नंबरों के साथ एक सूची है, और मुझे कुछ कोड लिखने की आवश्यकता है जो उन नंबरों के सभी 32,768 संयोजनों का उत्पादन करते हैं।

मुझे कुछ कोड (Googling द्वारा) मिले हैं, जो जाहिरा तौर पर वह है जो मैं देख रहा हूं, लेकिन मैंने कोड को काफी अपारदर्शी पाया और इसका उपयोग करने से सावधान हूं। इसके अलावा मुझे लगता है कि वहाँ एक और अधिक सुंदर समाधान होना चाहिए।

केवल एक चीज जो मुझे होती है वह दशमलव पूर्णांक 1–32768 के माध्यम से लूप करने और उन्हें द्विआधारी में बदलने के लिए होगी, और उपयुक्त संख्याओं को निकालने के लिए एक फ़िल्टर के रूप में द्विआधारी प्रतिनिधित्व का उपयोग करना होगा।

क्या कोई बेहतर तरीके से जानता है? का उपयोग कर map(), शायद?


9
पाठकों को ध्यान देना चाहिए कि क्या सूची आइटम अद्वितीय हैं , एक अत्यंत महत्वपूर्ण विचार है, क्योंकि कई एल्गोरिदम फिर कुछ सबसेट (जैसे 'abccc' -> ['', 'a', 'b', 'c', 'c') से आगे निकल जाएंगे। , 'c', 'ac', 'ac', 'ac', ...] एक आसान तरीका है कि सभी तत्वों को उनके क्रमांकन प्राप्त करने से पहले एक सेट में सभी तत्वों को अलग
दें

@njjagecko सेट लाइब्रेरी का उपयोग करना सबसे अच्छा नहीं है क्योंकि प्रत्येक O (n) सबसे अच्छे हैं। इस प्रकार सेट में n फ़ंक्शन जोड़ना वास्तव में O (n ^ 2) है!
स्कॉट बिग्स

प्रश्न को ध्यान से पढ़ने से, ऐसा लगता है कि ओपी सभी संख्याओं को नहीं, बल्कि 15 नंबरों की अपनी सूची के पावरसेट के लिए कह रहा है । मुझे लगता है कि यह हो सकता है कि सभी जगह जवाब क्यों हैं।
स्कॉट बिग्स

@ सेट बिग्स: क्या आप सुनिश्चित हैं कि आप यहां पायथन के बारे में ले रहे हैं? सम्मिलन और लुकअप सेट ओ (1) औसत मामला है। वे शब्दकोश की तरह हैं। वे हैशिंग का उपयोग करते हैं। पायथन में एक विशेष सेट लाइब्रेरी नहीं है (यह मानक पुस्तकालय में है)। हम यहां फ़ंक्शंस डाल रहे हैं, फ़ंक्शंस नहीं। (यह अभी भी O (2 ^ n) मेमोरी का उपयोग करने के लिए अक्षम होगा; जो लोग पावरसेट के बजाय संयोजन चाहते हैं उनके लिए उचित समाधान एक सरल पुनरावर्ती कार्यान्वयन है, या product, आदि)
Ninjagecko

जवाबों:


466

Itertools.combinations पर एक नज़र है :

itertools.combinations(iterable, r)

पुनरावृत्ति इनपुट से तत्वों की लंबाई लंबाई रिटर्न।

संयोजन शाब्दिक क्रम में उत्सर्जित होते हैं। इसलिए, यदि इनपुट पुनरावृत्त को हल किया जाता है, तो संयोजन ट्यूप को क्रमबद्ध क्रम में उत्पादित किया जाएगा।

2.6 के बाद से, बैटरी शामिल हैं!


31
आप बस इसे सूचीबद्ध कर सकते हैं। list(itertools.combinations(iterable, r))
सिलगॉन

1
क्या ऐसा कुछ भी है जिसकी आवश्यकता नहीं है r, अर्थात तत्वों के किसी भी लम्बाई के संयोजन।
mLstudent33

630

यह जवाब एक पहलू से चूक गया: ओपी ने सभी संयोजनों के लिए कहा ... न केवल लंबाई "आर" के संयोजन।

तो आपको या तो सभी लंबाई "एल" के माध्यम से लूप करना होगा:

import itertools

stuff = [1, 2, 3]
for L in range(0, len(stuff)+1):
    for subset in itertools.combinations(stuff, L):
        print(subset)

या - यदि आप स्नैज़ी प्राप्त करना चाहते हैं (या आपके बाद जो भी आपके कोड को पढ़ता है उसका दिमाग झुकता है) - आप "संयोजनों ()" जनरेटर की श्रृंखला उत्पन्न कर सकते हैं, और इसके माध्यम से पुनरावृत्ति कर सकते हैं:

from itertools import chain, combinations
def all_subsets(ss):
    return chain(*map(lambda x: combinations(ss, x), range(0, len(ss)+1)))

for subset in all_subsets(stuff):
    print(subset)

42
सहायता का शुक्रिया! जब से मैंने उपरोक्त उत्तर पोस्ट किया है, हफ्तों में, मैंने पाया है कि बेन के लिए जो अवधारणा है उसका NAME 15 वस्तुओं के मूल सेट का "अधिकार" है। वास्तव में, एक उदाहरण कार्यान्वयन मानक पायथन "itertools" doc पृष्ठ पर दिया गया है: docs.python.org/library/itertools.html ("पावरसेट" के लिए grep)।
डेन एच।

38
इसे पढ़ने वाले किसी भी व्यक्ति के लिए: प्रलेखनpowerset() के व्यंजनों अनुभाग में जनरेटर फ़ंक्शन सरल है, संभवतः कम मेमोरी का उपयोग करता है, और यहां दिखाए गए कार्यान्वयन की तुलना में तेज है। itertools
मार्टीन्यू

क्या लेक्सोग्राफिक क्रम में सभी संयोजनों को उत्पन्न करना संभव है?
गुइक

@ गुइक: मुझे 99% यकीन है कि itertools.combinationsसूची में आइटम क्रम को बरकरार रखता है जो इसकी पैदावार देता है। इस प्रकार, यदि इनपुट lexically सॉर्ट किया गया है, तो आउटपुट में से प्रत्येक भी होगा।
डैन एच।

हाँ, itertools.combinationsलेक्सोग्राफ़िक क्रम में n के बीच k का संयोजन उत्पन्न करता है, लेकिन n के बीच k तक के सभी संयोजन नहीं । k तकpowerset सभी संयोजनों को उत्पन्न करता है , लेकिन लेक्सिकोग्राफ़िक क्रम में नहीं जहां तक ​​मैं इसे समझता हूं: पावरसेट ([1,2]) -> [(), (1,), (2,), (1, 2)] । ऐसा नहीं होना चाहिए: [(), (1,), (1, 2), (2,)]?
गुह्य

52

यहाँ एक आलसी वन-लाइनर है, यह भी itertools का उपयोग कर:

from itertools import compress, product

def combinations(items):
    return ( set(compress(items,mask)) for mask in product(*[[0,1]]*len(items)) )
    # alternative:                      ...in product([0,1], repeat=len(items)) )

इस उत्तर के पीछे मुख्य विचार: 2 ^ N संयोजन हैं - समान लंबाई के बाइनरी स्ट्रिंग्स की संख्या। प्रत्येक बाइनरी स्ट्रिंग के लिए, आप "1" के अनुरूप सभी तत्वों को चुनते हैं।

items=abc * mask=###
 |
 V
000 -> 
001 ->   c
010 ->  b
011 ->  bc
100 -> a
101 -> a c
110 -> ab
111 -> abc

विचार करने के लिए बातें:

  • यह जरूरी है कि आप कॉल कर सकते हैं len(...)पर items(वैकल्पिक हल: अगर items, एक जनरेटर की तरह एक iterable की तरह कुछ है के साथ पहली बार एक सूची में बदल items=list(_itemsArg))
  • इसके लिए आवश्यक है कि पुनरावृति का क्रम itemsयादृच्छिक न हो (वर्कअराउंड: पागल मत बनो)
  • इसके लिए यह आवश्यक है कि आइटम अद्वितीय हों, या फिर {2,2,1}और {2,1,1}दोनों ही ढह जाएंगे {2,1}(वर्कअराउंड: इसके लिए collections.Counterड्रॉप-इन रिप्लेसमेंट के रूप में उपयोग करें set, यह मूल रूप से एक मल्टीसेट है ... हालांकि बाद में उपयोग करने की आवश्यकता हो सकती है tuple(sorted(Counter(...).elements()))यदि आपको इसे धोने के लिए आवश्यक है)

डेमो

>>> list(combinations(range(4)))
[set(), {3}, {2}, {2, 3}, {1}, {1, 3}, {1, 2}, {1, 2, 3}, {0}, {0, 3}, {0, 2}, {0, 2, 3}, {0, 1}, {0, 1, 3}, {0, 1, 2}, {0, 1, 2, 3}]

>>> list(combinations('abcd'))
[set(), {'d'}, {'c'}, {'c', 'd'}, {'b'}, {'b', 'd'}, {'c', 'b'}, {'c', 'b', 'd'}, {'a'}, {'a', 'd'}, {'a', 'c'}, {'a', 'c', 'd'}, {'a', 'b'}, {'a', 'b', 'd'}, {'a', 'c', 'b'}, {'a', 'c', 'b', 'd'}]

46

@ डैन एच द्वारा अत्यधिक उत्कीर्ण उत्तर के तहत टिप्पणियों में , उल्लेख स्वयं डैन द्वारा एक-एक करके प्रलेखनpowerset() में नुस्खा से बना है । हालाँकि , अभी तक किसी ने भी इसे उत्तर के रूप में पोस्ट नहीं किया है। चूंकि यह शायद बेहतर में से एक है यदि समस्या के लिए सबसे अच्छा तरीका नहीं - और किसी अन्य टिप्पणीकार से थोड़ा प्रोत्साहन दिया जाए , तो यह नीचे दिखाया गया है। फ़ंक्शन हर लंबाई की सूची तत्वों के सभी अद्वितीय संयोजनों को संभव बनाता है (जिनमें शून्य और सभी तत्व शामिल हैं)।itertools

नोट : यदि, सूक्ष्म रूप से भिन्न है, तो लक्ष्य केवल अद्वितीय तत्वों के संयोजन को प्राप्त करना है, किसी भी नकली तत्वों को खत्म s = list(iterable)करने के s = list(set(iterable))लिए लाइन को बदलना । बावजूद, तथ्य यह है कि iterableयह अंततः एक listसाधन में बदल जाता है, यह जनरेटर (अन्य उत्तरों के कई के विपरीत) के साथ काम करेगा।

from itertools import chain, combinations

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)  # allows duplicate elements
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

stuff = [1, 2, 3]
for i, combo in enumerate(powerset(stuff), 1):
    print('combo #{}: {}'.format(i, combo))

आउटपुट:

combo #1: ()
combo #2: (1,)
combo #3: (2,)
combo #4: (3,)
combo #5: (1, 2)
combo #6: (1, 3)
combo #7: (2, 3)
combo #8: (1, 2, 3)

list()पहले स्थान के लिए रूपांतरण क्या है ?
एएमसी

@ अलेक्जेंडर: चलने की लंबाई निर्धारित करने की अनुमति देने के लिए।
मार्टीन्यू

36

यहाँ एक पुनरावर्तन का उपयोग कर रहा है:

>>> import copy
>>> def combinations(target,data):
...     for i in range(len(data)):
...         new_target = copy.copy(target)
...         new_data = copy.copy(data)
...         new_target.append(data[i])
...         new_data = data[i+1:]
...         print new_target
...         combinations(new_target,
...                      new_data)
...                      
... 
>>> target = []
>>> data = ['a','b','c','d']
>>> 
>>> combinations(target,data)
['a']
['a', 'b']
['a', 'b', 'c']
['a', 'b', 'c', 'd']
['a', 'b', 'd']
['a', 'c']
['a', 'c', 'd']
['a', 'd']
['b']
['b', 'c']
['b', 'c', 'd']
['b', 'd']
['c']
['c', 'd']
['d']

क्या इसे मुद्रण की बजाय सूचियों की सूची में वापस लाने के लिए संशोधित किया जा सकता है?
जेम्स विक्री

@JamesVickery हाँ, आप या तो फ़ंक्शन के बाहर एक सूची बनाकर देख सकते हैं और उस पर
जोड़ सकते हैं

new_data = copy.copy(data)- यह पंक्ति जहाँ तक मैं देख रहा हूँ, यह निरर्थक है, यह किसी भी चीज़ पर प्रभाव नहीं डालती
दिमित्री फियाल्कोव्स्की

31

यह एक-लाइनर आप सभी संयोजनों देता है (के बीच 0और nआइटम मूल सूची / सेट होता है, तो nऔर अलग-अलग एलीमेंट) देशी विधि का उपयोग करता itertools.combinations:

अजगर २

from itertools import combinations

input = ['a', 'b', 'c', 'd']

output = sum([map(list, combinations(input, i)) for i in range(len(input) + 1)], [])

अजगर ३

from itertools import combinations

input = ['a', 'b', 'c', 'd']

output = sum([list(map(list, combinations(input, i))) for i in range(len(input) + 1)], [])

उत्पादन होगा:

[[],
 ['a'],
 ['b'],
 ['c'],
 ['d'],
 ['a', 'b'],
 ['a', 'c'],
 ['a', 'd'],
 ['b', 'c'],
 ['b', 'd'],
 ['c', 'd'],
 ['a', 'b', 'c'],
 ['a', 'b', 'd'],
 ['a', 'c', 'd'],
 ['b', 'c', 'd'],
 ['a', 'b', 'c', 'd']]

इसे ऑनलाइन आज़माएं:

http://ideone.com/COghfX


यह एक क्रमपरिवर्तन है
AdHominem

15
@ AdHominem: नहीं, यह नहीं है। यह सभी संयोजनों की सूची है। क्रमपरिवर्तन शामिल होंगे, जैसे ['b', 'a']
n

TypeError: can only concatenate list (not "map") to list
0x48piraj

@ 0x48piraj: ध्यान देने के लिए धन्यवाद, मैंने अपने उत्तर को फलस्वरूप संपादित किया!
मैथ्यू रोडिक

21

मैं डैन एच से सहमत हूं कि बेन वास्तव में सभी संयोजनों के लिए कहा था । itertools.combinations()सभी संयोजन नहीं देता है।

एक और मुद्दा है, यदि इनपुट चलने योग्य बड़ा है, तो शायद एक सूची में सब कुछ के बजाय एक जनरेटर वापस करना बेहतर है:

iterable = range(10)
for s in xrange(len(iterable)+1):
  for comb in itertools.combinations(iterable, s):
    yield comb

1
अच्छा उदाहरण है। मुझे जनरेटर पसंद हैं ... और मुझे उनके होने के लिए पायथन से प्यार है! इस उदाहरण में एक समय में केवल एक संयोजन () ऑब्जेक्ट होता है, और समय पर संयोजन में से एक को पैदावार देता है। (शायद आप इसके चारों ओर डिफ ब्लॉक को जोड़ना चाहते हैं - एक उपयोग उदाहरण के रूप में।) ध्यान दें कि मेरा कार्यान्वयन (श्रृंखला (), ऊपर दिया गया) बहुत बुरा नहीं है: यह सच है कि सभी लेन (चलने योग्य) जनरेटर बनाता है एक बार ... लेकिन यह एक साथ सभी 2 ** len (iterable) संयोजनों का निर्माण नहीं करता है, जैसे कि - मेरी समझ में - चेन "बाद वाले से ड्राइंग करने से पहले" पहले जनरेटर का उपयोग करता है।
Dan H

18

यह एक दृष्टिकोण है जिसे आसानी से सभी प्रोग्रामिंग भाषाओं में स्थानांतरित किया जा सकता है जो पुनरावृत्ति का समर्थन करता है (कोई पुनरावृत्ति नहीं, कोई उपज नहीं, कोई सूची नहीं है) :

def combs(a):
    if len(a) == 0:
        return [[]]
    cs = []
    for c in combs(a[1:]):
        cs += [c, c+[a[0]]]
    return cs

>>> combs([1,2,3,4,5])
[[], [1], [2], [2, 1], [3], [3, 1], [3, 2], ..., [5, 4, 3, 2, 1]]

14

आप इस सरल कोड का उपयोग करके अजगर में एक सूची के सभी संयोजनों को उत्पन्न कर सकते हैं

import itertools

a = [1,2,3,4]
for i in xrange(0,len(a)+1):
   print list(itertools.combinations(a,i))

परिणाम होगा:

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

इस कोड में बग: खाली सेट वापस नहीं करता है। इसका मतलब हो सकता है xrange (0, ...) लेकिन परीक्षण नहीं किया गया है। संपादित करें : मैं आगे गया और इसे ठीक करने के लिए आपके उत्तर को संपादित किया।
Ninjagecko

13

मैंने सोचा कि मैं इस फ़ंक्शन को इटर्स्टूल या किसी अन्य अतिरिक्त पुस्तकालयों को आयात किए बिना जवाब मांगने के लिए जोड़ूंगा।

def powerSet(items):
    """
    Power set generator: get all possible combinations of a list’s elements

    Input:
        items is a list
    Output:
        returns 2**n combination lists one at a time using a generator 

    Reference: edx.org 6.00.2x Lecture 2 - Decision Trees and dynamic programming
    """

    N = len(items)
    # enumerate the 2**N possible combinations
    for i in range(2**N):
        combo = []
        for j in range(N):
            # test bit jth of integer i
            if (i >> j) % 2 == 1:
                combo.append(items[j])
        yield combo

सरल उपज जनरेटर उपयोग:

for i in powerSet([1,2,3,4]):
    print (i, ", ",  end="")

ऊपर उपयोग उदाहरण से आउटपुट:

[], [१], [२], १, २], [३], [१, ३], [२, ३], [१, २, ३], [४], [१], १] , [२, ४], [१, २, ४], [३, ४], [१, ३, ४], [२, ३, ४], [१, २, ३, ४],


मुझे लगता है कि यह बहुत साफ समाधान है।
greentec

8

यहाँ अभी तक एक और समाधान (एक-लाइनर) है, जिसमें itertools.combinationsफ़ंक्शन का उपयोग करना शामिल है , लेकिन यहां हम एक डबल सूची समझ का उपयोग करते हैं (जैसा कि लूप या योग के लिए विरोध किया गया है):

def combs(x):
    return [c for i in range(len(x)+1) for c in combinations(x,i)]

डेमो:

>>> combs([1,2,3,4])
[(), 
 (1,), (2,), (3,), (4,), 
 (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4), 
 (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), 
 (1, 2, 3, 4)]

5
from itertools import permutations, combinations


features = ['A', 'B', 'C']
tmp = []
for i in range(len(features)):
    oc = combinations(features, i + 1)
    for c in oc:
        tmp.append(list(c))

उत्पादन

[
 ['A'],
 ['B'],
 ['C'],
 ['A', 'B'],
 ['A', 'C'],
 ['B', 'C'],
 ['A', 'B', 'C']
]

4

नीचे एक "मानक पुनरावर्ती उत्तर" है, जो अन्य समान उत्तर https://stackoverflow.com/a/23743696/71/85 के समान है । (हमें वास्तविक रूप से स्टैक स्पेस से बाहर निकलने के बारे में चिंता करने की ज़रूरत नहीं है क्योंकि कोई रास्ता नहीं है कि हम सभी एन-परम्यूटेशन को संसाधित कर सकें।)

यह बदले में हर तत्व का दौरा करता है, और या तो इसे ले जाता है या इसे छोड़ देता है (हम सीधे इस एल्गोरिथ्म से 2 ^ एन कार्डिनैलिटी देख सकते हैं)।

def combs(xs, i=0):
    if i==len(xs):
        yield ()
        return
    for c in combs(xs,i+1):
        yield c
        yield c+(xs[i],)

डेमो:

>>> list( combs(range(5)) )
[(), (0,), (1,), (1, 0), (2,), (2, 0), (2, 1), (2, 1, 0), (3,), (3, 0), (3, 1), (3, 1, 0), (3, 2), (3, 2, 0), (3, 2, 1), (3, 2, 1, 0), (4,), (4, 0), (4, 1), (4, 1, 0), (4, 2), (4, 2, 0), (4, 2, 1), (4, 2, 1, 0), (4, 3), (4, 3, 0), (4, 3, 1), (4, 3, 1, 0), (4, 3, 2), (4, 3, 2, 0), (4, 3, 2, 1), (4, 3, 2, 1, 0)]

>>> list(sorted( combs(range(5)), key=len))
[(), 
 (0,), (1,), (2,), (3,), (4,), 
 (1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2), (4, 3), 
 (2, 1, 0), (3, 1, 0), (3, 2, 0), (3, 2, 1), (4, 1, 0), (4, 2, 0), (4, 2, 1), (4, 3, 0), (4, 3, 1), (4, 3, 2), 
 (3, 2, 1, 0), (4, 2, 1, 0), (4, 3, 1, 0), (4, 3, 2, 0), (4, 3, 2, 1), 
 (4, 3, 2, 1, 0)]

>>> len(set(combs(range(5))))
32

2

सूची समझ का उपयोग करना:

def selfCombine( list2Combine, length ):
    listCombined = str( ['list2Combine[i' + str( i ) + ']' for i in range( length )] ).replace( "'", '' ) \
                     + 'for i0 in range(len( list2Combine ) )'
    if length > 1:
        listCombined += str( [' for i' + str( i ) + ' in range( i' + str( i - 1 ) + ', len( list2Combine ) )' for i in range( 1, length )] )\
            .replace( "', '", ' ' )\
            .replace( "['", '' )\
            .replace( "']", '' )

    listCombined = '[' + listCombined + ']'
    listCombined = eval( listCombined )

    return listCombined

list2Combine = ['A', 'B', 'C']
listCombined = selfCombine( list2Combine, 2 )

आउटपुट होगा:

['A', 'A']
['A', 'B']
['A', 'C']
['B', 'B']
['B', 'C']
['C', 'C']

4
इस प्रस्ताव को सेट बनाने के लिए स्ट्रिंग मैनलिंग करना है?!?! पवित्र कौवा .... और: यह पॉवरसेट वापस नहीं कर रहा है, बल्कि कुछ ऐसा है, जैसे कॉम्बिनेशन_विथ_रेसमेंट ()। (देखें docs.python.org/library/… )
दान एच

यह वास्तव में संयोजन_with_replacement () के रूप में ही करता है , लेकिन कम से कम मेरे बॉक्स पर यह itertools की तुलना में थोड़ा तेज चलता है । मैं क्या कह सकता हूं, मुझे सूची बोध पसंद है।
zmk

1
जवाब के लिए धन्यवाद! के बारे में सूची बनाने के बारे में उलट सूची जैसे ['ए', 'ए'], ['ए', 'बी'], ['ए', 'सी'], ['बी', 'ए'], [ 'बी', 'बी'], ['बी', 'सी'], ['सी', 'ए'], ['सी', 'बी'] और ['सी', 'सी'] जिनमें शामिल हैं सब कुछ?
Karyo

बहुत दिलचस्प है, लेकिन मेरे अजगर यहाँ सूक्ष्मताओं को समझने के लिए काफी नहीं है। क्या अलग-अलग स्कोपों ​​में सूचीबध्द का उपयोग करने के बारे में कुछ खास है और इस तथ्य के लिए कि लूप सभी एक पंक्ति में है? मैं इसे कम भाग्य के साथ जावा में पोर्ट करने की कोशिश कर रहा हूं।
स्कॉट बिग्स

2

यह कोड नेस्टेड सूचियों के साथ एक सरल एल्गोरिथ्म नियुक्त करता है ...

# FUNCTION getCombos: To generate all combos of an input list, consider the following sets of nested lists...
#
#           [ [ [] ] ]
#           [ [ [] ], [ [A] ] ]
#           [ [ [] ], [ [A],[B] ],         [ [A,B] ] ]
#           [ [ [] ], [ [A],[B],[C] ],     [ [A,B],[A,C],[B,C] ],                   [ [A,B,C] ] ]
#           [ [ [] ], [ [A],[B],[C],[D] ], [ [A,B],[A,C],[B,C],[A,D],[B,D],[C,D] ], [ [A,B,C],[A,B,D],[A,C,D],[B,C,D] ], [ [A,B,C,D] ] ]
#
#  There is a set of lists for each number of items that will occur in a combo (including an empty set).
#  For each additional item, begin at the back of the list by adding an empty list, then taking the set of
#  lists in the previous column (e.g., in the last list, for sets of 3 items you take the existing set of
#  3-item lists and append to it additional lists created by appending the item (4) to the lists in the
#  next smallest item count set. In this case, for the three sets of 2-items in the previous list. Repeat
#  for each set of lists back to the initial list containing just the empty list.
#

def getCombos(listIn = ['A','B','C','D','E','F'] ):
    listCombos = [ [ [] ] ]     # list of lists of combos, seeded with a list containing only the empty list
    listSimple = []             # list to contain the final returned list of items (e.g., characters)

    for item in listIn:
        listCombos.append([])   # append an emtpy list to the end for each new item added
        for index in xrange(len(listCombos)-1, 0, -1):  # set the index range to work through the list
            for listPrev in listCombos[index-1]:        # retrieve the lists from the previous column
                listCur = listPrev[:]                   # create a new temporary list object to update
                listCur.append(item)                    # add the item to the previous list to make it current
                listCombos[index].append(listCur)       # list length and append it to the current list

                itemCombo = ''                          # Create a str to concatenate list items into a str
                for item in listCur:                    # concatenate the members of the lists to create
                    itemCombo += item                   # create a string of items
                listSimple.append(itemCombo)            # add to the final output list

    return [listSimple, listCombos]
# END getCombos()

तो यह कोड क्या प्रतीत होता है वापसी [listOfCombifications, listOfCombmentsGroupedBySize]। दुर्भाग्य से जब डेमो इनपुट के साथ चलाया जाता है तो यह 64 के बजाय 63 तत्व देता है; यह खाली सेट (इस मामले में, रिक्त स्ट्रिंग "") को याद कर रहा है।
निंजाजेको

2

मुझे पता है कि सभी संयोजनों को प्राप्त करने के लिए itertools का उपयोग करना कहीं अधिक व्यावहारिक है , लेकिन आप इसे आंशिक रूप से केवल सूची समझ के साथ प्राप्त कर सकते हैं यदि आप इच्छा के साथ ऐसा करते हैं, तो आप बहुत कुछ कोड करना चाहते हैं

दो जोड़ों के संयोजन के लिए:

    lambda l: [(a, b) for i, a in enumerate(l) for b in l[i+1:]]


और, तीन जोड़ों के संयोजन के लिए, यह इस रूप में आसान है:

    lambda l: [(a, b, c) for i, a in enumerate(l) for ii, b in enumerate(l[i+1:]) for c in l[i+ii+2:]]


परिणाम itertools.combinations का उपयोग करने के लिए समान है:

import itertools
combs_3 = lambda l: [
    (a, b, c) for i, a in enumerate(l) 
    for ii, b in enumerate(l[i+1:]) 
    for c in l[i+ii+2:]
]
data = ((1, 2), 5, "a", None)
print("A:", list(itertools.combinations(data, 3)))
print("B:", combs_3(data))
# A: [((1, 2), 5, 'a'), ((1, 2), 5, None), ((1, 2), 'a', None), (5, 'a', None)]
# B: [((1, 2), 5, 'a'), ((1, 2), 5, None), ((1, 2), 'a', None), (5, 'a', None)]

2

Itertools का उपयोग किए बिना:

def combine(inp):
    return combine_helper(inp, [], [])


def combine_helper(inp, temp, ans):
    for i in range(len(inp)):
        current = inp[i]
        remaining = inp[i + 1:]
        temp.append(current)
        ans.append(tuple(temp))
        combine_helper(remaining, temp, ans)
        temp.pop()
    return ans


print(combine(['a', 'b', 'c', 'd']))

2

यहाँ के दो कार्यान्वयन हैं itertools.combinations

एक है कि एक सूची देता है

def combinations(lst, depth, start=0, items=[]):
    if depth <= 0:
        return [items]
    out = []
    for i in range(start, len(lst)):
        out += combinations(lst, depth - 1, i + 1, items + [lst[i]])
    return out

एक जेनरेटर लौटाता है

def combinations(lst, depth, start=0, prepend=[]):
    if depth <= 0:
        yield prepend
    else:
        for i in range(start, len(lst)):
            for c in combinations(lst, depth - 1, i + 1, prepend + [lst[i]]):
                yield c

कृपया ध्यान दें कि उन लोगों के लिए एक सहायक समारोह प्रदान करने की सलाह दी जाती है क्योंकि प्रीपेन्ड तर्क स्थिर है और हर कॉल के साथ नहीं बदल रहा है

print([c for c in combinations([1, 2, 3, 4], 3)])
# [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]

# get a hold of prepend
prepend = [c for c in combinations([], -1)][0]
prepend.append(None)

print([c for c in combinations([1, 2, 3, 4], 3)])
# [[None, 1, 2, 3], [None, 1, 2, 4], [None, 1, 3, 4], [None, 2, 3, 4]]

यह एक बहुत ही सतही मामला है लेकिन खेद से बेहतर होना सुरक्षित है


2

इसके बारे में कैसे .. सूची के बजाय एक स्ट्रिंग का इस्तेमाल किया, लेकिन एक ही बात .. स्ट्रिंग को पायथन में एक सूची की तरह माना जा सकता है:

def comb(s, res):
    if not s: return
    res.add(s)
    for i in range(0, len(s)):
        t = s[0:i] + s[i + 1:]
        comb(t, res)

res = set()
comb('game', res) 

print(res)

2

Itertools से संयोजन

import itertools
col_names = ["aa","bb", "cc", "dd"]
all_combinations = itertools.chain(*[itertools.combinations(col_names,i+1) for i,_ in enumerate(col_names)])
print(list(all_combinations))

धन्यवाद



2

3 कार्य:

  1. n तत्वों की सूची के सभी संयोजन
  2. n तत्वों की सूची के सभी संयोजन जहां ऑर्डर अलग नहीं है
  3. सभी क्रमपरिवर्तन
import sys

def permutations(a):
    return combinations(a, len(a))

def combinations(a, n):
    if n == 1:
        for x in a:
            yield [x]
    else:
        for i in range(len(a)):
            for x in combinations(a[:i] + a[i+1:], n-1):
                yield [a[i]] + x

def combinationsNoOrder(a, n):
    if n == 1:
        for x in a:
            yield [x]
    else:
        for i in range(len(a)):
            for x in combinationsNoOrder(a[:i], n-1):
                yield [a[i]] + x

if __name__ == "__main__":
    for s in combinations(list(map(int, sys.argv[2:])), int(sys.argv[1])):
        print(s)

मुझे यह बहुत पसंद है!!! धन्यवाद!!! पाइथन के कॉम्बिनेटरिक्स कार्य हालांकि थोड़ा अजीब हैं। गणित में "कॉम्बिनेशन" फंक्शन वेरिएशन होगा, और "कॉम्बिनेशन नोऑर्डर" वास्तव में कॉम्बिनेशन हैं। मुझे लगता है कि लोगों को भ्रमित करता है कि गणित की शाखा से अजगर आते हैं, जैसा कि इस बार मेरे साथ हुआ। वैसे भी, एक अच्छा समाधान, बहुत बहुत धन्यवाद!
अयुमी ब्रानिसलव

1

यह मेरा कार्यान्वयन है

    def get_combinations(list_of_things):
    """gets every combination of things in a list returned as a list of lists

    Should be read : add all combinations of a certain size to the end of a list for every possible size in the
    the list_of_things.

    """
    list_of_combinations = [list(combinations_of_a_certain_size)
                            for possible_size_of_combinations in range(1,  len(list_of_things))
                            for combinations_of_a_certain_size in itertools.combinations(list_of_things,
                                                                                         possible_size_of_combinations)]
    return list_of_combinations

1
यहां लागू किए गए पिछले कार्यान्वयन की तुलना में आपका कार्यान्वयन बेहतर क्या है?
user1767754

0

आप उत्कृष्ट पैकेज से भी पॉवरसेट फ़ंक्शन का उपयोग कर सकते हैं more_itertools

from more_itertools import powerset

l = [1,2,3]
list(powerset(l))

# [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

हम यह भी सत्यापित कर सकते हैं, कि यह ओपी की आवश्यकता को पूरा करता है

from more_itertools import ilen

assert ilen(powerset(range(15))) == 32_768

-1
def combinations(iterable, r):
# combinations('ABCD', 2) --> AB AC AD BC BD CD
# combinations(range(4), 3) --> 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
    return
indices = range(r)
yield tuple(pool[i] for i in indices)
while True:
    for i in reversed(range(r)):
        if indices[i] != i + n - r:
            break
    else:
        return
    indices[i] += 1
    for j in range(i+1, r):
        indices[j] = indices[j-1] + 1
    yield tuple(pool[i] for i in indices)


x = [2, 3, 4, 5, 1, 6, 4, 7, 8, 3, 9]
for i in combinations(x, 2):
    print i

1
अगर मैं सही हूं, तो यह सटीक कोड है जिसे अजगर प्रलेखन [ docs.python.org/3.6/library/itertools.html ] से कॉपी किया गया है । यदि हां, तो कृपया स्रोत को देखें।
गेब्रियलचू

रुचिकर दृष्टिकोण
पेलोस

-1

अगर कोई उलटी सूची की तलाश में है, जैसे मैं था:

stuff = [1, 2, 3, 4]

def reverse(bla, y):
    for subset in itertools.combinations(bla, len(bla)-y):
        print list(subset)
    if y != len(bla):
        y += 1
        reverse(bla, y)

reverse(stuff, 1)

-1
flag = 0
requiredCals =12
from itertools import chain, combinations

def powerset(iterable):
    s = list(iterable)  # allows duplicate elements
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

stuff = [2,9,5,1,6]
for i, combo in enumerate(powerset(stuff), 1):
    if(len(combo)>0):
        #print(combo , sum(combo))
        if(sum(combo)== requiredCals):
            flag = 1
            break
if(flag==1):
    print('True')
else:
    print('else')
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.