तानाशाह (कुंजी) काम क्यों नहीं किया लेकिन तानाशाही [की]?


17

मैं स्ट्रिंग में कितने 1 के आधार पर कुछ संख्याओं के बाइनरी स्ट्रिंग्स को एक साथ समूहित करने की कोशिश कर रहा हूं।

यह काम नहीं करता है:

s = "0 1 3 7 8 9 11 15"
numbers = map(int, s.split())
binaries = [bin(x)[2:].rjust(4, '0') for x in numbers]

one_groups = dict.fromkeys(range(5), [])
for x in binaries:
    one_groups[x.count('1')] += [x]

अपेक्षित शब्दकोश one_groupsहोना चाहिए

{0: ['0000'], 
 1: ['0001', '1000'], 
 2: ['0011', '1001'], 
 3: ['0111', '1011'], 
 4: ['1111']}

लेकिन मुझे मिलता है

{0: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 1: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 2: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 3: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 4: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111']}

अब तक केवल एक चीज है जो काम की है अगर मैं one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]इसके बजाय उपयोग करता हूंone_groups[x.count('1')] += [x]

लेकिन ऐसा क्यों है? यदि मैं सही ढंग से याद करता हूं, तो dict[key]उस शब्दकोश के मूल्य को वापस नहीं करना चाहिए , यह कैसे dict.get(key)काम करता है? मैंने इस धागे को तानाशाह [कुंजी] के बजाय तानाशाही (कुंजी) क्यों देखा है ? लेकिन यह इस विशेष मामले के लिए मेरे सवाल का जवाब नहीं दिया, क्योंकि मुझे पता है कि कार्यक्रम प्राप्त करने के लिए नहीं हैKeyError

मैंने भी कोशिश की है one_groups[x.count('1')].append(x)लेकिन यह भी काम नहीं करता है।


8
getNoneयदि कुंजी मौजूद नहीं है या कोई डिफ़ॉल्ट मान प्रदान नहीं करता है, तो वापस लौटें , जबकि इंडेक्स ऑपरेटर []कुंजी नहीं होने पर एक त्रुटि उठाता है।
अदनमुट्टलेब

सिडेनोट, bin(x)[2:].rjust(4, '0')को सरल बनाया जा सकता है '{:0>4b}'.format(x)
wjandrea 2

1
BTW यह एक न्यूनतम प्रतिलिपि प्रस्तुत करने योग्य उदाहरण बनाने में मदद करता है । इस मामले में आप कैसे बनाते हैं binariesयह सवाल के लिए प्रासंगिक नहीं है, इसलिए आप बस इसका मूल्य प्रदान कर सकते हैं।
वेजेंड्रिया

1
क्या इससे आपके सवाल का जवाब मिलता है? dict.fromkeys एक ही सूची में सभी बिंदु
जॉर्जी

जवाबों:


24

समस्या उत्परिवर्तन है:

one_groups = dict.fromkeys(range(5), [])- यह सभी कुंजियों के मान के समान सूची पास करता है । इसलिए यदि आप एक मूल्य बदलते हैं, तो आप उन सभी को बदलते हैं।

यह मूल रूप से कहने के समान है:

tmp = []
one_groups = dict.fromkeys(range(5), tmp)
del tmp

यदि आप एक नई सूची का उपयोग करना चाहते हैं, तो आपको इसे लूप में करने की आवश्यकता है - या तो एक स्पष्ट forलूप या एक तानाशाह में।

one_groups = {key: [] for key in range(5)}

यह बात हर कुंजी के लिए "निष्पादित" [](जो बराबर list()) होती है , इस प्रकार विभिन्न सूचियों के साथ मान बनाती है।


getकाम क्यों करता है ? क्योंकि आप स्पष्ट रूप से वर्तमान सूची लेते हैं, लेकिन +एक नई परिणाम सूची बनाते हैं। और इससे कोई फर्क नहीं पड़ता कि यह है one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]या one_groups[x.count('1')] = one_groups[x.count('1')] + [x]- क्या मायने रखता है +

मुझे पता है कि हर कोई a+=bबस कैसे कहता है a=a+b, लेकिन कार्यान्वयन अनुकूलन के लिए अलग हो सकता है - सूचियों के मामले में, +=सिर्फ .extendइसलिए कि हम जानते हैं कि हम वर्तमान चर में अपना परिणाम चाहते हैं, इसलिए नई सूची बनाना स्मृति की बर्बादी होगी।


आह, हाँ, समझा। मुझे यह भी याद है कि इसी तरह की समस्या होने पर मैं एक 2 डी सूची का उपयोग कर बनाना चाहता था mylist = [[] * 5] * 5और यह कैसे mylist = [[] for x in range(5)] * 5तय किया होगा। बस त्वरित स्पष्टीकरण के लिए, मुझे समझ से, यह उस खाली सूची के मेमोरी एड्रेस की ओर इशारा करते हुए चरों के कारण होता है। इसका मतलब यह भी है कि अगर मैं इसके बजाय आदिम का उपयोग करता तो समस्या नहीं होती?
स्पेक्ट्रा XCD

1
हां, यदि आपने प्राइमिटिव्स का उपयोग किया है तो यह इसे हल करेगा, लेकिन टूट जाएगा one_groups[x.count('1')] += [x]क्योंकि आप एक सूची को एक आदिम प्रकार में नहीं जोड़ सकते। इसके बजाय बकाए का उपयोग करने के लिए एक बेहतर समाधान है।
फखर मोकैडे

4
विशेष रूप से, +कॉल करता है __add__और एक नई वस्तु देता है, जबकि +=कॉल करता है __iadd__, और एक नई वस्तु को वापस करने की आवश्यकता नहीं होती है
njzk2

8

समस्या का उपयोग कर रहा है one_groups = dict.fromkeys(range(5), [])

(यह सभी कुंजियों के मान के समान सूची पास करता है। इसलिए यदि आप एक मान को बदलते हैं, तो आप उन सभी को बदल देते हैं)


आप इसके बजाय इसका उपयोग कर सकते हैं: one_groups = {i:[] for i in range(5)}

(यह बात प्रत्येक कुंजी के लिए "निष्पादित" [] (जो सूची के बराबर होती है) (इस प्रकार विभिन्न सूचियों के साथ मान बना रही है)


6
आप बिल्कुल सही हैं, हालांकि एक स्पष्टीकरण वास्तव में उपयोगी होगा। यह वास्तव में नहीं है कि दोनों लाइनों के बीच अंतर क्या है।
सिमोन फिंक

हाँ, यह मेरा बुरा है। क्षमा करें
Hameda169

4

यह तानाशाही fromkeysपद्धति पर सहायता है ।

अंतर्निहित फ़ंक्शन से सहायता मिलती है:

fromkeys (चलने योग्य, मूल्य = कोई नहीं, /) बिल्टइन की विधि। उदाहरण उदाहरण चलने योग्य और मान से सेट मानों के साथ एक नया शब्दकोश बनाएं

यह कहता है कि गदहे एक मूल्य को स्वीकार करेंगे, और यहां तक ​​कि यह एक कॉल करने योग्य है, यह पहले इसका मूल्यांकन करेगा, और फिर उस मूल्य को सभी तानाशाह कुंजी को सौंप देगा।

पाइथन में सूचियाँ उत्परिवर्तनीय हैं, और इसलिए यह एक ही खाली सूची संदर्भ प्रदान करेगा और एक परिवर्तन उन सभी को प्रभावित करेगा।

इसके बजाय डिफ़ॉल्ट निर्णय का उपयोग करें:

>>> from collections import defaultdict
>>> one_groups = defaultdict(list)
>>> for x in binaries:
      one_groups[x.count('1')] += [x]
>>> one_groups = dict(one_groups) # to stop default dict behavior

यह गैर-मौजूदा कुंजी को असाइनमेंट स्वीकार करेगा और मान खाली सूचियों (इस मामले में) के लिए डिफ़ॉल्ट होगा।

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