2011-01-19 11 views
9

मैं सोच रहा था कि क्या आप मेरे कोड के प्रदर्शन को बेहतर बनाने के संबंध में मुझे कुछ सलाह दे सकते हैं।बड़े शब्दकोशों के लिए dict.keys() प्रदर्शन में python key

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

dict={} 
for value in value_list: 
    if value.key in dict.keys(): 
     temp_list = dict[value.key] 
     temp_list.append(value.val) 
     dict[value.key] = temp_list 
    else: 
     dict[value.key] = [value.val] 

के लिए अब इस कोड ठीक काम करता है, लेकिन evenrually शब्दकोश dict.keys में लाइन value.key() अधिक से अधिक बोझिल हो जाता है को भरने के लिए शुरू होता है के रूप में।

क्या ऐसा करने का कोई बेहतर तरीका है?

धन्यवाद,

माइक

+2

बस दो छोटे नोट्स: 1) '... dict.keys() में:' को संक्षिप्त किया जा सकता है ... 'dict: '। 2) चर के निर्माण के बाद चर का नाम नहीं रखा जाना चाहिए - इस मामले में, 'dict' नाम बदलने पर विचार करें। – miku

+0

बेहतर तरीके से आपका क्या मतलब है? सरल या तेज़? –

उत्तर

37

करने के लिए सरल किया जा सकता है ऐसा मत करो:

value.key in dict.keys() 

कि - में पायथन 2, ले पर Ast - प्रत्येक कुंजी युक्त एक सूची बनाता है। यह अधिक से अधिक महंगा हो जाता है क्योंकि शब्दकोश बड़ा हो जाता है, और कुंजी खोजने के लिए सूची में ओ (एन) खोज करता है, जो एक नियम का उपयोग करने के उद्देश्य को हरा देता है।

इसके बजाय, बस करो:

value.key in dict 

जो एक अस्थायी सूची का निर्माण नहीं करता है, और कुंजी के बजाय एक रेखीय खोज के लिए एक हैश तालिका देखने करता है।

setdefault, जैसा कि कहीं और बताया गया है, यह करने का क्लीनर तरीका है, लेकिन उपरोक्त को समझना बहुत महत्वपूर्ण है।

+0

धन्यवाद अपने सभी तेजी से प्रतिक्रिया के लिए, अपने सभी मदद – Werda

+0

कुछ वास्तविक जानकारी है कि सराहना की तरह। धन्यवाद – Kaunteya

4

collections.defaultdict का उपयोग करना, इस

d = collections.defaultdict(list) 
for value in value_list: 
    d[value.key].append(value.val) 
+0

क्या कोड को तेज़ी से चलाने या एक ही चीज़ को लिखने का एक सरल (छोटा) तरीका बनाता है? –

+0

@Saher: यह निश्चित रूप से मूल संस्करण है, जो 'इस्तेमाल किया dict.keys()' प्रत्येक चरण में, हर बार कुंजी की बढ़ती सूची निकालने की तुलना में तेजी है। यह शायद एक बिट से [sberry2A के समाधान] (http://stackoverflow.com/questions/4730993/python-key-in-dict-keys-performance-for-large-dictionaries/4731022#4731022), लेकिन बहुत से नहीं धीमी है बहुत। –

+0

'setdefault' ज्यादातर समय' डिफ़ॉल्टdict' से बेहतर है। आमतौर पर कक्षा को बदलने का अर्थ नहीं होता है जब आप जो करना चाहते हैं वह एक विशेष ऑपरेशन बदलना है। यदि आप वास्तव में * हमेशा * इस व्यवहार को चाहते हैं तो केवल 'डिफ़ॉल्ट डिक्ट' का उपयोग करें। –

1
if value.key in dict.keys(): 

बहुत महंगा है क्योंकि आप कुंजी की सूची में परिवर्तित हो रहे हैं और फिर सूची खोज रहे हैं। बस की जगह उस के साथ:

if value.key in dict: 

छोटा चाहिए खोज ~ लॉग ऑन एन करने के लिए (संपादित करें: मैं द्वारा सही मानी ग्लेन, शायद भी तेजी क्योंकि अजगर शब्दकोशों एक हैश तालिका का उपयोग करें)। फिर बस:

dict[key].append(value.val) 

चीजों को थोड़ा सा गति देना चाहिए। एक अस्थायी का उपयोग करने की आवश्यकता नहीं है और बस कुछ सीपीयू चक्र खाती है।

यदि आप जो कुछ करने की कोशिश कर रहे हैं उसके बारे में अधिक जानकारी दे सकते हैं तो कोई बेहतर एल्गोरिदम सुझा सकता है।

+1

dict lookups ओ (लॉग एन) नहीं हैं। वे एक हैश टेबल हैं, पेड़ नहीं। –

+0

@Glenn: बहुत से एसटीडी कर दिया गया :: नक्शे का आनंद लें :-) मुझे लगता है कि इतने सारे लोग हर सवाल का जवाब देने भागने के साथ सवाल पूछ लोगों की कमी नहीं है ... :-) –

2

चरण 1: append विधि के बजाय अतिरिक्त उपयोग करके, हम temp_list का उपयोग एक अभिव्यक्ति में कोड को बदलते हैं (मुझे लगता है कि temp_list इस कोड के बाहर की आवश्यकता नहीं है)। इसके अलावा, हमें स्पष्ट रूप से dict.keys() का उपयोग करने की आवश्यकता नहीं है, जैसा कि अन्य ने उल्लेख किया है (और वास्तव में यह बहुत अधिक समय बर्बाद करता है)।

for value in value_list: 
    if value.key in dict: 
     dict[value.key] = dict[value.key] + [value.val] 
    else: 
     dict[value.key] = [value.val] 

चरण 2: सशर्त अभिव्यक्ति वाक्य रचना का उपयोग करके कार्य करने वाली-ही-स्थान परिवर्तित करें।

for value in value_list: 
    dict[value.key] = dict[value.key] + [value.val] if value.key in dict else [value.val] 

चरण 3: जोड़ना या एक खाली सूची prepending एक सूची के मूल्य पर कोई प्रभाव नहीं है, तो हम है कि सम्मिलित कर सकते हैं, और फिर मूल्य के आम 'इसके अलावा' को अलग।

for value in value_list: 
    dict[value.key] = (dict[value.key] if value.key in dict else []) + [value.val] 

चरण 4: एक 'डिफ़ॉल्ट' मूल्य प्रदान करने के लिए पहचानो कि dict में निर्मित कार्यक्षमता है जब कुंजी अनुपस्थित है:

for value in value_list: 
    dict[value.key] = dict.get(value.key, []) + [value.val] 

चरण 5: इसके बजाय एक मूल्य के होने का, इसे संशोधित और इसे वापस स्थापित करने, हम .setdefault उपयोग कर सकते हैं हमें मौजूदा सामग्री देने के लिए (या उन्हें सेट अप नहीं करता है, तो पहले से ही वहाँ), और फिर .append का उपयोग कर सूची को संशोधित करने के लिए वापस स्विच:

for value in value_list: 
    dict.setdefault(value.key, []).append(value.val) 

(मेरा मतलब है ... मैं तो बस इसे देखा सकता है और कुछ देर सोचा और इस पर पहुंचे, लेकिन प्रत्येक चरण को देख यह स्पष्ट है जहाँ हम जा रहे हैं बनाता है ...)

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