2011-02-17 13 views
215

क्या निम्नलिखित कोड काम करने के लिए defaultdict(defaultdict(int)) है?पायथन: डिफ़ॉल्ट डिक्शन का डिफ़ॉल्ट डिक्ट?

for x in stuff: 
    d[x.a][x.b] += x.c_int 

dx.a और x.b तत्वों पर तदर्थ, आधार बनाया जाना चाहिए।

मैं इस्तेमाल कर सकते हैं:

for x in stuff: 
    d[x.a,x.b] += x.c_int 

लेकिन फिर मैं उपयोग करने के लिए सक्षम नहीं होगा:

d.keys() 
d[x.a].keys() 
+3

इसी तरह के प्रश्न देखें [_ पायथन में नेस्टेड शब्दकोशों को लागू करने का सबसे अच्छा तरीका क्या है? _] (Http://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested- शब्दकोशों में अजगर)। [_Autovivification_] (https://en.wikipedia.org/wiki/Autovivification#Python) पर विकिपीडिया के लेख में कुछ संभावित रूप से उपयोगी जानकारी भी है। – martineau

उत्तर

383

हाँ इस तरह:

defaultdict(lambda: defaultdict(int)) 

एक defaultdict का तर्क (इस मामले में lambda: defaultdict(int)) कॉल किया जाएगा जब आप उस कुंजी तक पहुंचने का प्रयास करेंगे जो अस्तित्व में नहीं है। इसका वापसी मूल्य इस कुंजी के नए मान के रूप में सेट किया जाएगा, जिसका अर्थ है कि हमारे मामले में d[Key_doesnt_exist] का मान defaultdict(int) होगा।

यदि आप इस अंतिम डिफ़ॉल्ट डिक्शनरी से किसी कुंजी तक पहुंचने का प्रयास करते हैं, तो d[Key_doesnt_exist][Key_doesnt_exist] यह 0 लौटाएगा, जो पिछले डिफ़ॉल्ट डिक्शनरी के तर्क का वापसी मूल्य है यानी int()

+6

यह बहुत अच्छा काम करता है! क्या आप इस वाक्यविन्यास के पीछे तर्कसंगत व्याख्या कर सकते हैं? – Jonathan

+31

@ जोनाथन: हां, निश्चित रूप से, 'डिफॉल्टडिक्ट' का तर्क (इस मामले में 'लैम्ब्डा: डिफॉल्ट डिक्ट (इंट) ') कहा जाएगा जब आप उस कुंजी तक पहुंचने का प्रयास करते हैं जो मौजूद नहीं है और इसका वापसी मूल्य होगा इस कुंजी के नए मान के रूप में सेट किया जाना चाहिए जिसका मतलब है कि हमारे मामले में 'd [Key_dont_exist]' का मान 'डिफ़ॉल्ट' (int) 'होगा, और यदि आप इस अंतिम डिफ़ॉल्ट डिक्शनरी से एक कुंजी तक पहुंचने का प्रयास करते हैं यानी 'd [Key_dont_exist] [Key_dont_exist] 'यह 0 लौटाएगा जो अंतिम '' डिफ़ॉल्ट डिक्शन' यानी 'int()' के तर्क का वापसी मान है, उम्मीद है कि यह सहायक था। – mouad

+22

'डिफॉल्टडिक्ट' के लिए तर्क एक फ़ंक्शन होना चाहिए। 'डिफ़ॉल्ट डिक्ट (int) 'एक शब्दकोश है, जबकि' lambda: defaultdict (int) 'फ़ंक्शन है जो एक शब्दकोश देता है। – has2k1

40

डिफॉल्टडिक्ट कन्स्ट्रक्टर का पैरामीटर वह कार्य है जिसे नए तत्व बनाने के लिए बुलाया जाएगा। तो चलो एक लैम्ब्डा का उपयोग करें!

अजगर 2.7 के बाद से
>>> from collections import defaultdict 
>>> d = defaultdict(lambda : defaultdict(int)) 
>>> print d[0] 
defaultdict(<type 'int'>, {}) 
>>> print d[0]["x"] 
0 

, वहाँ एक even better solution using Counter:

>>> from collections import Counter 
>>> c = Counter() 
>>> c["goodbye"]+=1 
>>> c["and thank you"]=42 
>>> c["for the fish"]-=5 
>>> c 
Counter({'and thank you': 42, 'goodbye': 1, 'for the fish': -5}) 

कुछ बोनस सुविधाओं

>>> c.most_common()[:2] 
[('and thank you', 42), ('goodbye', 1)] 

अधिक जानकारी के लिए देख PyMOTW - Collections - Container data types और Python Documentation - collections

+4

बस यहां सर्कल को पूरा करने के लिए, आप मूल रूप से उत्पन्न होने वाली समस्या को विशेष रूप से संबोधित करने के लिए 'd = defaultdict (lambda: defaultdict (int)) के बजाय' d = defaultdict (lambda: काउंटर()) 'का उपयोग करना चाहते हैं। – gumption

+1

@ गम्प्शन आप इस मामले में 'l = defaultdict (काउंटर()) का उपयोग कर सकते हैं' इस मामले में लैम्ब्डा की कोई आवश्यकता नहीं – Deb

23

मैं इसे थोड़ा और अधिक करने के लिए सुरुचिपूर्ण लगता है partial का उपयोग करें :

import functools 
dd_int = functools.partial(defaultdict, int) 
defaultdict(dd_int) 

बेशक, यह लैम्ब्डा जैसा ही है।

6

दूसरों कैसे काम करने के लिए निम्न प्राप्त करने के लिए सही ढंग से अपने प्रश्न का उत्तर है:

for x in stuff: 
    d[x.a][x.b] += x.c_int 

एक वैकल्पिक चाबी के लिए tuples उपयोग करने के लिए होगा:

d = defaultdict(int) 
for x in stuff: 
    d[x.a,x.b] += x.c_int 
    # ^^^^^^^ tuple key 

इस विधि की अच्छी बात है यह आसान है और आसानी से विस्तार किया जा सकता है। यदि आपको तीन स्तरों के गहरे मैपिंग की आवश्यकता है, तो कुंजी के लिए केवल तीन आइटम टुपल का उपयोग करें।

+4

इस समाधान का मतलब है कि सभी डी [xa] प्राप्त करना आसान नहीं है, क्योंकि आपको हर कुंजी का आत्मनिरीक्षण करने की आवश्यकता है यह देखने के लिए कि क्या यह xa tuple के पहले तत्व के रूप में है। –

+5

यदि आप 3 स्तरों को गहराई से घोंसले करना चाहते थे, तो बस इसे 3 स्तरों के रूप में परिभाषित करें: डी = डिफ़ॉल्ट डिक्ट (लैम्ब्डा: डिफॉल्टडिक्ट (लैम्ब्डा: डिफॉल्टडिक्ट (int))) –

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