2014-05-11 5 views
5

के साथ किसी शब्दकोश से आइटम को हटाने से मैं कुंजी के मान को निश्चित सीमा से नीचे होने पर एक शब्दकोश से आइटम ड्रॉप करने का प्रयास कर रहा हूं। मैं क्या मतलब है के लिए एक सरल उदाहरण के लिए:लूप

my_dict = {'blue': 1, 'red': 2, 'yellow': 3, 'green': 4} 

for color in my_dict: 
    threshold_value = 3 
    if my_dict[color] < threshold_value: 
     del my_dict[color] 

print(my_dict) 

अब, मैं एक RuntimeError: dictionary changed size during iteration त्रुटि मिलती है। वहां कोई बड़ी आश्चर्य नहीं है। कारण है कि मैं इस प्रश्न पोस्ट कर रहा हूँ है:

  1. हो, तो एक सुरुचिपूर्ण समाधान एक नया शब्दकोश बनाने की आवश्यकता नहीं है कि (उस के साथ मूल्यों> = सीमा केवल कुंजी रखती है) जानकारी प्राप्त करें।

  2. यहां पाइथन के तर्क को समझने का प्रयास करें। जिस तरह से मैंने इसे स्वयं पढ़ा है: "पहली कुंजी पर जाएं। क्या उस कुंजी का मान < x है? यदि हां - यह कुंजी डेल करें: मान आइटम और शब्दकोश में अगली कुंजी पर जारी रखें, यदि नहीं - जारी रखें कुछ भी किए बिना अगली कुंजी "। दूसरे शब्दों में, पिछली चाबियों के लिए ऐतिहासिक रूप से क्या हुआ, इससे मुझे प्रभावित नहीं होना चाहिए। अतीत के बावजूद, मैं अगले आइटम की प्रतीक्षा कर रहा हूं। मुझे पता है कि यह एक मजेदार है (कुछ बेवकूफ कह सकते हैं, मैं आपको वह दूंगा) लेकिन इस पाश के बारे में पाइथन का "सोचने का तरीका" क्या है? यह क्यों काम नहीं करता है? पाइथन इसे अपने आप से ज़ोर से कैसे पढ़ेगा? बस तथ्य यह है कि अजगर शब्दकोशों हैश तालिकाओं के रूप में लागू किया जाता है के कारण भाषा का एक बेहतर समझ प्राप्त करने की कोशिश ...

उत्तर

10

, आप एक आदेश किसी भी प्रकार का होने उन पर भरोसा नहीं करना चाहिए। मुख्य आदेश अप्रत्याशित रूप से बदल सकता है (लेकिन केवल कुंजी के सम्मिलन या हटाने के बाद)। इस प्रकार, अगली कुंजी की भविष्यवाणी करना असंभव है। पाइथन सुरक्षित होने के लिए RuntimeError फेंकता है, और लोगों को अप्रत्याशित परिणामों में भागने से रोकने के लिए।

अजगर 2 के dict.items विधि देता है एक कॉपी कुंजी-मान जोड़ों का, तो आप सुरक्षित रूप से मान, कुंजी द्वारा की जरूरत नहीं है के रूप में @wim टिप्पणी में सुझाव दिया इस पर पुनरावृति और हटा सकते हैं। उदाहरण:

for k, v in my_dict.items(): 
    if v < threshold_value: 
     del my_dict[k] 

हालांकि, अजगर 3 के dict.items एक view object कि शब्दकोश में किए गए सभी परिवर्तन को दर्शाता है देता है। यही कारण है कि उपरोक्त समाधान केवल पायथन 2 में काम करता है। आप इसे पाइथन 3-संगत बनाने के लिए my_dict.items() से list (tuple आदि) को परिवर्तित कर सकते हैं।

समस्या दृष्टिकोण एक और तरीका है कुंजी आप हटाना चाहते हैं और चयन करने के लिए तो उन्हें

keys = [k for k, v in my_dict.items() if v < threshold_value] 
for x in keys: 
    del my_dict[x] 

यह दोनों अजगर 2 और अजगर में काम करता है 3.

2

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

बस एक नया बना:

my_dict = {"blue":1,"red":2,"yellow":3,"green":4} 
new_dict = {k:v for k,v in my_dict.iteritems() if v >= threshold_value} 
+0

जैसा कि मैंने ओपी में कहा था, मैं एक नया नियम नहीं बनाना चाहता हूं। – Optimesh

+0

आपने एक सुरुचिपूर्ण तरीके से पूछा। लेकिन आप जो भी चाहें प्रोग्राम कर सकते हैं। – Daniel

0

मुझे लगता है कि एक संग्रह को संशोधित इस पर पुनरावृत्ति करते हुए ठीक से लागू करने के लिए क्या करने के लिए एक मुश्किल बात है। निम्नलिखित exaple पर विचार करें:

>>> list = [1, 2, 3, 4, 5, 6] 
>>> for ii in range(len(list)): 
    print list[ii]; 
    if list[ii] == 3: 
    del list[ii]  
1 
2 
3 
5 
6 

ध्यान दें कि इस उदाहरण में 4 पूरी तरह से छोड़ा गया था।यह शब्दकोशों में बहुत ही सरल है, प्रविष्टियों को हटाने/जोड़ने से आंतरिक संरचनाओं को अमान्य कर दिया जा सकता है जो पुनरावृत्ति के क्रम को परिभाषित करते हैं (उदाहरण के लिए आपने पर्याप्त प्रविष्टियों को हटा दिया है, इसलिए हैश नक्शा बाल्टी आकार बदल गया है)।

अपने मामले को हल करने के लिए --- बस नया शब्दकोश बनाएं और वहां आइटम कॉपी करें। जैसा कि मैंने ओपी में कहा था,