सवाल जांचें कि किसी दिए गए कुंजी को किसी शब्दकोश में पहले से मौजूद है या नहीं


मैं परीक्षण करना चाहता था कि कुंजी के मान को अपडेट करने से पहले एक कुंजी में एक कुंजी मौजूद है या नहीं। मैंने निम्नलिखित कोड लिखा:

if 'key1' in dict.keys():
  print "blah"
else:
  print "boo"

मुझे लगता है कि यह काम पूरा करने का यह सबसे अच्छा तरीका नहीं है। क्या शब्दकोश में कुंजी के लिए परीक्षण करने का कोई बेहतर तरीका है?


2189
2017-10-21 19:05


मूल


कॉलिंग dict.keys() प्रलेखन के अनुसार, चाबियों की एक सूची बनाता है docs.python.org/2/library/stdtypes.html#dict.keys लेकिन मुझे आश्चर्य होगा अगर इस पैटर्न को गंभीर कार्यान्वयन में, अनुवाद करने के लिए अनुकूलित नहीं किया गया था if 'key1' in dict:। - Evgeni Sergeev
तो मुझे अंततः पता चला कि मेरी कई पाइथन स्क्रिप्ट इतनी धीमी क्यों थीं :) :( ऐसा इसलिए है क्योंकि मैं इसका उपयोग कर रहा हूं x in dict.keys() चाबियों की जांच करने के लिए। और ऐसा इसलिए हुआ क्योंकि जावा में चाबियों को फिर से चलाने का सामान्य तरीका है for (Type k : dict.keySet()), इस आदत का कारण बनता है for k in dict.keys() से अधिक प्राकृतिक महसूस करने के लिए for k in dict (जो अभी भी प्रदर्शन के मामले में ठीक होना चाहिए?), लेकिन फिर जांच कुंजी बन जाती है if k in dict.keys() भी, जो एक समस्या है ... - Evgeni Sergeev
@EvgeniSergeev if k in dict_: dict_ की कुंजी में k की उपस्थिति के लिए परीक्षण, इसलिए आपको अभी भी आवश्यकता नहीं है dict_.keys()। (यह मुझे थोड़ा सा है, क्योंकि यह मेरे लिए इसके परीक्षण की तरह मुझे पढ़ता है मूल्य dict में लेकिन यह नहीं है।) - ToolmakerSteve
@ToolmakerSteve यह सही है, लेकिन न केवल आपको इसकी आवश्यकता नहीं है, यह एक अच्छा अभ्यास नहीं है। - Evgeni Sergeev
"Dict में कुंजी" आज़माएं - marcelosalloum


जवाब:


in एक कुंजी के अस्तित्व के लिए परीक्षण करने का इरादा तरीका है dict

d = dict()

for i in xrange(100):
    key = i % 10
    if key in d:
        d[key] += 1
    else:
        d[key] = 1

यदि आप एक डिफ़ॉल्ट चाहते थे, तो आप हमेशा उपयोग कर सकते हैं dict.get():

d = dict()

for i in xrange(100):
    key = i % 10
    d[key] = d.get(key, 0) + 1

... और यदि आप हमेशा किसी भी कुंजी के लिए डिफ़ॉल्ट मान सुनिश्चित करना चाहते हैं जिसका आप उपयोग कर सकते हैं defaultdict वहाँ से collections मॉड्यूल, जैसे:

from collections import defaultdict

d = defaultdict(lambda: 0)

for i in xrange(100):
    d[i % 10] += 1

... लेकिन सामान्य रूप से, in कीवर्ड इसे करने का सबसे अच्छा तरीका है।


2242
2017-10-21 19:10



मैं आमतौर पर बस उपयोग करते हैं get अगर मैं वैसे भी आइटम को बाहर खींचने जा रहा हूं। उपयोग करने में कोई समझ नहीं है in  तथा आइटम को शब्दकोश से बाहर खींच रहा है। - Jason Baker
में पूरी तरह से सहमत हूँ। लेकिन अगर आपको केवल यह पता होना चाहिए कि कोई कुंजी मौजूद है या आपको किसी ऐसे मामले के बीच अंतर करने की आवश्यकता है जहां कुंजी परिभाषित की गई है और एक मामला जहां आप डिफ़ॉल्ट का उपयोग कर रहे हैं, in ऐसा करने का सबसे अच्छा तरीका है। - Chris B.
संदर्भ इस उत्तर के लिए अजगर दस्तावेज़ों पर है - enkash
यदि कुंजी "गलत" के बराबर है, तो एक खराब परीक्षण प्राप्त करें 0 उदाहरण के लिए। इसे कठिन तरीके से सीख लिया: / - Sebastien
मैं इस बात से सहमत नहीं हो सकता कि यह एक पूर्ण उत्तर है क्योंकि इसमें उल्लेख नहीं है कि 'कोशिश' - 'छोड़कर' सबसे तेज़ होगा जब कुंजी विफल होने की संख्या पर्याप्त रूप से छोटी होगी। नीचे यह उत्तर देखें: stackoverflow.com/a/1602945/4376643 - Craig Hicks


आपको चाबियाँ कॉल करने की ज़रूरत नहीं है:

if 'key1' in dict:
  print "blah"
else:
  print "boo"

वह बहुत होगा और तेज चूंकि यह एक रैखिक खोज करने के विरोध में शब्दकोश के हैशिंग का उपयोग करता है, जो कॉलिंग कुंजी करेगा।


1099
2017-10-21 19:06



यह बहुत बढ़िया बात है। मैं इस धारणा के तहत था कि यह आंतरिक रूप से अभी भी चाबियों की सूची को पार करेगा, लेकिन मुझे लगता है कि यह एक सेट में सदस्यता सदस्यता की तरह काम करता है। - Mohan Gulati
@ मोहन गुलाटी: आप समझते हैं कि एक शब्दकोश मूल्यों के लिए मैप किए गए चाबियों का हैशटेबल है, है ना? एक हैशिंग एल्गोरिदम कुंजी को एक पूर्णांक में परिवर्तित करता है और पूर्णांक का उपयोग हैश तालिका में एक स्थान खोजने के लिए किया जाता है। en.wikipedia.org/wiki/Hash_table - hughdbrown
@ चार्ल्स एडिस, लगभग आधे मिलियन कुंजियों के साथ काम करने वाले अनुभव से आपको कम से कम 10x प्रदर्शन बढ़ावा मिलता है जब "dict.keys (key" में कुंजी "के बजाय" कुंजी में "लिखना होता है। पीईपी और जेन यह भी बताते हैं कि यदि आप अपनी परियोजना के लिए बुरे हैं तो आपको उन्हें अनदेखा करना चाहिए। - ivan_bilan
ivan_bilan - मैंने बस इस पर अपना खुद का बेंचटेस्ट चलाया ... आधे मिलियन चाबियों पर, if key in d1 लिया 0.17265701293945312 सेकंड। कॉलिंग if key in d1.keys() लिया 0.23871088027954102 - यह सूक्ष्म अनुकूलन की क्लासिक परिभाषा है। बचत 0.07884883880615234 सेकंड प्रदर्शन प्रदर्शन नहीं है। - Charles Addis
@Eli बस आपके लिए मैंने एक परीक्षण बनाया है जिसे आप स्वयं चला सकते हैं। परिणाम आपको आश्चर्यचकित कर सकते हैं। ~ 50,000 कुंजी के साथ डिक्ट्स के लिए, कॉल नहीं keys() आपको .01 दूसरा कम्प्यूटेशनल लाभ देता है। ~ 500,000 कुंजी के लिए, कॉल नहीं keys() आपको 1 दूसरा लाभ देता है। ~ 5,000,000 कुंजी के लिए, कॉल नहीं keys() 4 सेकंड तेज है, लेकिन 50,000,000 कुंजी के लिए कॉल कर रहा है keys() 3 सेकंड तेज है! - Charles Addis


आप का उपयोग कर एक शब्दकोश में एक कुंजी की उपस्थिति के लिए परीक्षण कर सकते हैं में कीवर्ड:

d = {'a': 1, 'b': 2}
'a' in d # <== evaluates to True
'c' in d # <== evaluates to False

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

पुराने कोड में, आपको कुछ उपयोग भी मिल सकते हैं has_key(), शब्दकोशों में कुंजी के अस्तित्व की जांच के लिए एक बहिष्कृत विधि (बस उपयोग करें key_name in dict_name, बजाय)।


226
2017-10-21 19:16



dict.has_key (कुंजी) को dict में कुंजी के पक्ष में बहिष्कृत कर दिया गया है - David Locke
तकनीकी तौर पर, has_key है पदावनत पायथन 2.x + के लिए (केवल 3.0+ के लिए नहीं)। यही है, पाइथन 2.x में लिखते समय भी इसका उपयोग न करने के लिए नए कोड की अनुशंसा की जाती है। (क्योंकि यह एक विशेषता है जो भविष्य के संस्करणों में जा रही है, और इसके बजाय उपयोग करने के लिए एक बिल्कुल अच्छा विकल्प है।) 3.0 में क्या होता है यह है कि इसे पूरी तरह से हटा दिया जाता है। - ToolmakerSteve
@ToolmakerSteve आप निश्चित रूप से सही हैं और मैंने इसे प्रतिबिंबित करने के लिए उत्तर अपडेट किया है। :) - kqr
इसे साझा करना चाहता था (पायथन 2.7 का उपयोग करके) मैंने जो लिखा है, उसके रन टाइम का समय, डिक्ट्स पर भारी आधार पर, 363.235070 था "dict.keys () में" कुंजी "का उपयोग करके और पूरी तरह से" कुंजी "के लिए कॉल को हटाकर 0.260186 पर चला गया। ) " - Ido_f
@Ido_f कृपया अपने मानक पोस्ट करें, क्योंकि मेरे बेंचमार्क 3.5 और 2.7 में लगभग कोई अंतर नहीं है - Charles Addis


आप इसे छोटा कर सकते हैं:

if 'key1' in dict:
    ...

हालांकि, यह सबसे अच्छा कॉस्मेटिक सुधार है। आपको विश्वास क्यों है कि यह सबसे अच्छा तरीका नहीं है?


74
2017-10-21 19:06



ये है बहुत एक कॉस्मेटिक सुधार से अधिक। इस विधि का उपयोग कर कुंजी खोजने का समय ओ (1) है जबकि कॉलिंग कुंजी एक सूची उत्पन्न करेगी और ओ (एन) होगी। - Jason Baker
ओ (1) काफी सही प्रतीत नहीं होता है। क्या आप वाकई ओ (लॉग एन) की तरह कुछ नहीं हैं? - spectras
यह एक एकल धुन लुकअप की जटिलता है, जो औसतन ओ (1) और सबसे खराब ओ (एन) पर है। .list () हमेशा ओ (एन) होगा। wiki.python.org/moin/TimeComplexity - Leo Tindall


मैं उपयोग करने की सिफारिश करेंगे setdefault इसके बजाय विधि। ऐसा लगता है जैसे यह सब कुछ आप चाहते हैं।

>>> d = {'foo':'bar'}
>>> q = d.setdefault('foo','baz') #Do not override the existing key
>>> print q #The value takes what was originally in the dictionary
bar
>>> print d
{'foo': 'bar'}
>>> r = d.setdefault('baz',18) #baz was never in the dictionary
>>> print r #Now r has the value supplied above
18
>>> print d #The dictionary's been updated
{'foo': 'bar', 'baz': 18}

40
2017-10-21 19:07



क्या करता है setdefault ओपी के सवाल के साथ क्या करना है? - hughdbrown
@hughdbrown "मैं जांचना चाहता था कि कुंजी के लिए मान अद्यतन करने से पहले एक कुंजी में एक कुंजी मौजूद है या नहीं।" कभी-कभी पोस्ट में कोड शामिल होता है जो प्रतिक्रियाओं की झुकाव उत्पन्न करता है जो कि मूल लक्ष्य नहीं है। पहले वाक्य में दिए गए लक्ष्य को पूरा करने के लिए, सेटडेफॉल्ट सबसे प्रभावी तरीका है, भले ही यह पोस्ट किए गए नमूना कोड के लिए ड्रॉप-इन प्रतिस्थापन न हो। - David Berger
यह बेहतर जवाब है क्योंकि यह तकनीकी रूप से सही उत्तर देने के बजाय ओपी के लक्ष्य को पूरा करता है। देख: nedbatchelder.com/blog/201207/... - Niels Bom
एक सूचनात्मक उत्तर के लिए +1, जिसने मुझे कुछ सिखाया। हालांकि, क्या यह सबसे अच्छा समाधान है कि कोडर के मन में क्या है; जैसे "कुंजी के मूल्य को अद्यतन करने से पहले" का अर्थ। हो सकता है कि वह एक अपवाद फेंकने जा रहा है यदि यह मौजूद नहीं है (== नई कुंजी जोड़ने की अनुमति नहीं है)। हो सकता है कि यह गणना का एक शब्दकोश है, और वह मौजूदा गिनती में 1 जोड़ने जा रहा है, जिस स्थिति में `डी [कुंजी] = डी .get (कुंजी, 0) + 1 'सबसे साफ समाधान है (क्रिस शो के रूप में, आपके उत्तर के बाद लिखा गया था)। (मैं केवल इस बात का जिक्र करने में परेशान हूं, अगर भविष्य के पाठक यहां विभिन्न कार्यों के साथ आते हैं।) - ToolmakerSteve
@NielsBom ... IMHO setdefault है केवल  बेहतर समाधान जब एक मौजूदा प्रविष्टि चाहिए नहीं ओवरराइट किया जाना चाहिए। (एक महत्वपूर्ण मामला, लेकिन एक कुंजी के अस्तित्व का परीक्षण करने का एकमात्र कारण नहीं है।) - ToolmakerSteve


स्वीकृत उत्तर के प्रस्तावित तरीकों (10 मीटर लूप) की गति निष्पादन पर अतिरिक्त जानकारी के लिए:

  • 'key' in mydict विलुप्त समय 1.07 सेकंड
  • mydict.get('key') समय समाप्त हो गया 1.84 सेकंड
  • mydefaultdict['key'] विलुप्त समय 1.07 सेकंड

इसलिए उपयोग कर रहे हैं in या defaultdict के खिलाफ सिफारिश की जाती है get


35
2018-05-29 11:06



संक्षेप में बुलेट अंक 1 और 3 का संयोजन प्राप्त करें .. - scape
पूरी तरह से सहमत हैं कि get1.84 है <1.07 * 2; -पी - Paul Rigor


पाइथन में शब्दकोश एक प्राप्त ('कुंजी', डिफ़ॉल्ट) विधि है। इसलिए यदि कोई कुंजी नहीं है तो आप केवल एक डिफ़ॉल्ट मान सेट कर सकते हैं।

values = {...}
myValue = values.get('Key', None)

19
2018-03-01 09:03





जांच के लिए आप उपयोग कर सकते हैं has_key() तरीका

if dict.has_key('key1'):
   print "it is there"

यदि आप एक मूल्य चाहते हैं तो आप इसका उपयोग कर सकते हैं get() तरीका

a = dict.get('key1', expeced_type)

यदि आप एक टुपल या सूची या शब्दकोश या किसी स्ट्रिंग को डिफ़ॉल्ट मान के रूप में डिफ़ॉल्ट मान के रूप में चाहते हैं, तो उपयोग करें get() तरीका

a = dict.get('key1', {}).get('key2', [])

15
2017-09-10 18:37



.get और है_की पहले से ही आपके उत्तर के वर्षों में सुझाव दिया गया है, है_की को पायथन 3 में भी हटा दिया गया है - Padraic Cunningham


टर्नरी ऑपरेटर का उपयोग करना:

message = "blah" if 'key1' in dict else "booh"
print(message)

14
2017-08-18 22:58





ईएएफपी का उपयोग करने के बारे में क्या (अनुमति से क्षमा मांगना आसान है):

try:
   blah = dict["mykey"]
   # key exists in dict
except KeyError:
   # key doesn't exist in dict

अन्य एसओ पोस्ट देखें:

पाइथन में कोशिश बनाम कोशिश कर रहे हैं या

पायथन में सदस्य अस्तित्व की जांच


14
2018-02-06 16:08



कोशिश करें / छोड़कर अधिक महंगा हो सकता है यदि यह संभव है कि कुंजी अक्सर मौजूद न हो। आपके द्वारा संदर्भित पोस्ट से: "[I] f आप उम्मीद करते हैं कि 99% समय के परिणाम में वास्तव में कुछ हड़ताली होगी, मैं कोशिश / छोड़ने के दृष्टिकोण का उपयोग करता हूं। अगर अपवाद वास्तव में असाधारण हैं तो यह तेज़ होगा। यदि परिणाम कोई नहीं है 50% से अधिक समय, तो यदि संभवतः बेहतर है तो इसका उपयोग करें। [...] [ए] एन अगर कथन हमेशा आपको खर्च करता है, तो यह कोशिश / ब्लॉक को छोड़कर लगभग मुक्त है। लेकिन जब एक अपवाद वास्तव में होता है, तो लागत बहुत अधिक है। " stackoverflow.com/a/1835844/1094092 - billrichards
एक नंगे पकड़ के बजाय मैं निर्दिष्ट करता हूं except KeyError यहाँ। - shuttle87


बस एक एफवाईआई क्रिस को जोड़ रहा है। बी (सर्वश्रेष्ठ जवाब):

d = defaultdict(int)

साथ ही काम करता है; कारण यह है कि कॉलिंग int() रिटर्न 0 कौन क्या है defaultdict दृश्यों के पीछे (एक शब्दकोश का निर्माण करते समय), इसलिए दस्तावेज़ में "फैक्टरी फ़ंक्शन" नाम है।


13
2018-05-19 18:12



(मैंने आपको +1 दिया, क्योंकि क्रिस ' defaultdict(lambda: 0) मुझे अस्पष्ट लग रहा था। कह रही है "यह int का एक शब्दकोश है, इसलिए वे एक int के डिफ़ॉल्ट मान से शुरू होते हैं, उदाहरण के लिए int () उदा। 0" मुझे पसंद है।) - ToolmakerSteve
यदि आप गणना का शब्दकोश बना रहे हैं, तो आपको इसका उपयोग करना चाहिए काउंटर (पायथन 2.7 मानते हैं)। और मैंने इस्तेमाल किया defaultdict(lambda: 0) के बजाय defaultdict(int) क्योंकि मुझे लगता है कि यह स्पष्ट है कि क्या हो रहा है; पाठक को आपको यह जानने की आवश्यकता नहीं है कि आपको मिलता है 0 अगर आप कॉल करते हैं int() तर्क के बिना। YMMV। - Chris B.