2010-10-06 5 views
23

मेरे पास निम्नलिखित आने वाले मान हैं:पायथन का उपयोग कर सूची मूल्यों के साथ शब्दकोश से संयोजन

variants = { 
    "debug" : ["on", "off"], 
    "locale" : ["de_DE", "en_US", "fr_FR"], 
    ... 
} 

मैं उन्हें संसाधित करना चाहता हूं इसलिए मुझे निम्न परिणाम मिलता है:

combinations = [ 
    [{"debug":"on"},{"locale":"de_DE"}], 
    [{"debug":"on"},{"locale":"en_US"}], 
    [{"debug":"on"},{"locale":"fr_FR"}], 
    [{"debug":"off"},{"locale":"de_DE"}], 
    [{"debug":"off"},{"locale":"en_US"}], 
    [{"debug":"off"},{"locale":"fr_FR"}] 
] 

यह शब्दकोश में कुंजी की मनमानी लंबाई के साथ काम करना चाहिए। पायथन में itertools के साथ खेला, लेकिन इन आवश्यकताओं से मेल खाने वाली कुछ भी नहीं मिला।

+1

क्या आप वाकई दो तत्वों की सूची नहीं चाहते हैं? – SilentGhost

उत्तर

31
import itertools as it 

varNames = sorted(variants) 
combinations = [dict(zip(varNames, prod)) for prod in it.product(*(variants[varName] for varName in varNames))] 

हम्म, यह रिटर्न:

[{'debug': 'on', 'locale': 'de_DE'}, 
{'debug': 'on', 'locale': 'en_US'}, 
{'debug': 'on', 'locale': 'fr_FR'}, 
{'debug': 'off', 'locale': 'de_DE'}, 
{'debug': 'off', 'locale': 'en_US'}, 
{'debug': 'off', 'locale': 'fr_FR'}] 

जो शायद बिल्कुल नहीं, तुम क्या चाहते है। मुझे इसके लिए अनुकूल हैं ...

combinations = [ [ {varName: val} for varName, val in zip(varNames, prod) ] for prod in it.product(*(variants[varName] for varName in varNames))] 

रिटर्न अब:

[[{'debug': 'on'}, {'locale': 'de_DE'}], 
[{'debug': 'on'}, {'locale': 'en_US'}], 
[{'debug': 'on'}, {'locale': 'fr_FR'}], 
[{'debug': 'off'}, {'locale': 'de_DE'}], 
[{'debug': 'off'}, {'locale': 'en_US'}], 
[{'debug': 'off'}, {'locale': 'fr_FR'}]] 

Voilà ;-)

+0

वाह, वह तेज़ और बिल्कुल वही था जो मैं ढूंढ रहा था। धन्यवाद दोस्त। कभी-कभी पूछना आपके लिए कई घंटों की कोशिश करने से बहुत तेज़ है। –

+2

वास्तव में आपका पहला समाधान मेरे लिए बेहतर उपयोग योग्य है। आपके द्वारा दूसरी बार निर्मित एक के लिए पूछने के लिए सिर्फ एक गलत धारणा थी :) –

1

मैं आप सभी चाबियों का कार्तीय उत्पाद चाहते हैं मान? तो यदि आपके पास एक और प्रविष्टि थी, "foo", मानों [1, 2, 3] के साथ, तो आपके पास 18 कुल प्रविष्टियां होंगी?

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

[[{'debug': 'on'}, {'debug': 'off'}], [{'locale': 'de_DE'}, {'locale': 'en_US'}, {'locale': 'fr_FR'}]] 

कि ऐसा करने के लिए:

>>> stuff = [] 
>>> for k,v in variants.items(): 
    blah = [] 
    for i in v: 
     blah.append({k:i}) 
    stuff.append(blah) 


>>> stuff 
[[{'debug': 'on'}, {'debug': 'off'}], [{'locale': 'de_DE'}, {'locale': 'en_US'}, {'locale': 'fr_FR'}]] 

अगला हम यह विस्तार करने के लिए एक कार्तीय उत्पाद समारोह का उपयोग कर सकते हैं ...

>>> def cartesian_product(lists, previous_elements = []): 
if len(lists) == 1: 
    for elem in lists[0]: 
     yield previous_elements + [elem, ] 
else: 
    for elem in lists[0]: 
     for x in cartesian_product(lists[1:], previous_elements + [elem, ]): 
      yield x 


>>> list(cartesian_product(stuff)) 
[[{'debug': 'on'}, {'locale': 'de_DE'}], [{'debug': 'on'}, {'locale': 'en_US'}], [{'debug': 'on'}, {'locale': 'fr_FR'}], [{'debug': 'off'}, {'locale': 'de_DE'}], [{'debug': 'off'}, {'locale': 'en_US'}], [{'debug': 'off'}, {'locale': 'fr_FR'}]] 

ध्यान दें कि यह नहीं करता है डिक्ट्स की प्रतिलिपि न लें, इसलिए सभी {'debug': 'on'} डिक्ट्स समान हैं।

+0

हे हास्यास्पद यह सब कोड पहले एक-लाइनर के बराबर है। यह जानकर अच्छा लगा कि cartesian_product अंतर्निहित है, मैं कभी नहीं जानता था! – Claudiu

+0

itertools.product (और संयोजन, और क्रमपरिवर्तन) पायथन 2.6 में itertools के लिए एक महान इसके अलावा था। हालांकि, मुझे नाम पसंद नहीं है।जैसा कि आप लिखते हैं, "cartesian_product", उत्पाद एक पुनरावृत्त तत्वों का उत्पाद होना चाहिए: कम करें (operator.mul, it) – tokland

+0

तो आपके पास 18 कुल प्रविष्टियां होंगी? हां :) जो मैं चाहता हूं उसका नाम नया नहीं था। पारितोषिक के लिए धन्यवाद। –

7
combinations = [[{key: value} for (key, value) in zip(variants, values)] 
       for values in itertools.product(*variants.values())] 

[[{'debug': 'on'}, {'locale': 'de_DE'}], 
[{'debug': 'on'}, {'locale': 'en_US'}], 
[{'debug': 'on'}, {'locale': 'fr_FR'}], 
[{'debug': 'off'}, {'locale': 'de_DE'}], 
[{'debug': 'off'}, {'locale': 'en_US'}], 
[{'debug': 'off'}, {'locale': 'fr_FR'}]] 
3

यह मैं क्या उपयोग है:

from itertools import product 

def dictproduct(dct): 
    for t in product(*dct.itervalues()): 
     yield dict(zip(dct.iterkeys(), t)) 

जो आपके उदाहरण के लिए लागू देता है:

>>> list(dictproduct({"debug":["on", "off"], "locale":["de_DE", "en_US", "fr_FR"]})) 
[{'debug': 'on', 'locale': 'de_DE'}, 
{'debug': 'on', 'locale': 'en_US'}, 
{'debug': 'on', 'locale': 'fr_FR'}, 
{'debug': 'off', 'locale': 'de_DE'}, 
{'debug': 'off', 'locale': 'en_US'}, 
{'debug': 'off', 'locale': 'fr_FR'}] 

मुझे लगता है इस के ऊपर एक लाइनर्स की तुलना में अधिक पठनीय है।

इसके अलावा, यह itertools.product जैसे पुनरावर्तक को लौटाता है, इसलिए यह उपयोगकर्ता को छोड़ देता है कि सूची को तुरंत चालू करना है या एक समय में मूल्यों का उपभोग करना है।

संबंधित मुद्दे