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


294

एक शब्दकोश को देखते हुए, मैं कैसे पता लगा सकता हूं कि उस शब्दकोश में दी गई कुंजी पहले से ही गैर-मूल्य के लिए सेट की गई है?

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

my_dict = {}

if (my_dict[key] != None):
  my_dict[key] = 1
else:
  my_dict[key] += 1

यानी, मैं मूल्य बढ़ाना चाहता हूं अगर वहां पहले से ही एक है, या इसे 1 पर सेट करें अन्यथा।


11
छोटा कोड नाइटपिक: कोड my_dict [कुंजी] को 1 पर सेट करता है अगर वहाँ पहले से ही कुछ है, और अगर वहाँ नहीं है तो इसे बढ़ाता है। मुझे लगता है कि आप चाहते हैं ==, नहीं! =।
क्वांटमफुल

जवाबों:


331

आप देख रहे हैं collections.defaultdict(पायथन 2.5+ के लिए उपलब्ध)। इस

from collections import defaultdict

my_dict = defaultdict(int)
my_dict[key] += 1

जो चाहोगे, करोगे।

नियमित पायथन dicts के लिए, यदि किसी दिए गए कुंजी के लिए कोई मूल्य नहीं है, तो आपको हुकुम तक पहुंचते समय नहीं मिलेगा None- एक KeyErrorउठाया जाएगा। इसलिए यदि आप dictअपने कोड के बजाय एक नियमित उपयोग करना चाहते हैं, तो आप उपयोग करेंगे

if key in my_dict:
    my_dict[key] += 1
else:
    my_dict[key] = 1

8
उनके उदाहरण के अनुसार, यह "डिफॉल्टडिक्ट (लैम्ब्डा: 0)" सेट करने के लिए पर्याप्त होना चाहिए और "क्लॉज" होने पर पूरे को छोड़ दें।
देस्तान

यह काम करता है, लेकिन कुंजी और मूल्यों को भ्रमित करता है (इसे पढ़ने के लिए कुछ अजीब है)। 'some_value' 'some_key' होना चाहिए
mikemaccana

@ नाविक: तय, धन्यवाद। मैंने शुरू में 'some_value' का उपयोग किया था क्योंकि यह प्रश्न में परिवर्तनशील नाम है, लेकिन मैं मानता हूं कि यह अब स्पष्ट है।
डीएफ।

20
... या नियमित dictएस के लिए, आप कर सकते हैं my_dict[key] = my_dict.get(key, 0) + 1
माइनमाक्सगव

इसे नेस्टेड शब्दकोशों में कैसे विस्तारित किया जाए? तानाशाह [की १] [की २] + = १?
पाब्लो रुइज

300

मैं कोड की एक पंक्ति में ऐसा करना पसंद करता हूं।

my_dict = {}

my_dict [some_key] = my_dict.get (some_key, 0) + 1

शब्दकोशों में एक फ़ंक्शन होता है, प्राप्त करें, जो दो मापदंडों को लेता है - कुंजी जिसे आप चाहते हैं, और डिफ़ॉल्ट मान यदि मौजूद नहीं है। मैं इस विधि को डिफ़ॉल्ट रूप से पसंद करता हूं क्योंकि आप केवल उस मामले को संभालना चाहते हैं जहां कुंजी कोड की इस एक पंक्ति में मौजूद नहीं है, हर जगह नहीं।


1
@AndrewWilkinson मेरा बुरा। आपके उत्तर को पूरी तरह से नहीं पढ़ा, जैसा कि मुझे करना चाहिए था।
मास्टर्स

59

मुझे व्यक्तिगत रूप से उपयोग करना पसंद है setdefault()

my_dict = {}

my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1

setdefaultकमाल है। यदि पहले से ही सेट है, तो यह मान को परिवर्तित नहीं करता है some_key। उदाहरण के लिए, d={1:2}; d.setdefault(1, 0)के मूल्य को परेशान नहीं करता है d[1]
wsaleem

49

उसके लिए आपको key in dictमुहावरे की आवश्यकता है।

if key in my_dict and not (my_dict[key] is None):
  # do something
else:
  # do something else

हालांकि, आपको संभवतः उपयोग करना चाहिए defaultdict(जैसा कि डीएफ ने सुझाव दिया है)।


1
कृपया ध्यान दें कि d में कुंजी के पक्ष में कम से कम 2.6 has_key () को हटा दिया गया है। मुझे लगता है कि यह 2.5 में भी इस तरह से था।
डेविड लॉक

ध्यान दें कि कोई भी लिख सकता है my_dict[key] is not None, जो स्पष्ट है (IMHO कम से कम)
ब्रांडीज़ी

@brandizzi - सहमत हैं,if key in my_dict and my_dict[key]:
रोब ग्रांट

18

इस सवाल का जवाब देने के लिए कि " मैं कैसे पता लगा सकता हूं कि उस दिए गए इंडेक्स में कोई गैर-कोई मूल्य पहले से ही निर्धारित किया गया है ", मैं इसे पसंद करूंगा:

try:
  nonNone = my_dict[key] is not None
except KeyError:
  nonNone = False

यह ईएएफपी (पहले से माफी मांगने की अनुमति के लिए आसान) की पहले से लागू अवधारणा के अनुरूप है। यह शब्दकोश में डुप्लिकेट कुंजी लुकअप से भी बचता है क्योंकि key in my_dict and my_dict[key] is not Noneयदि लुकअप महंगा है तो यह दिलचस्प है।

वास्तविक समस्या के लिए जिसे आपने पेश किया है, अर्थात यदि यह मौजूद है, तो एक इंट्री बढ़ाना, या इसे डिफ़ॉल्ट मान पर सेट करना अन्यथा, मैं भी इसकी सिफारिश करता हूं

my_dict[key] = my_dict.get(key, default) + 1

एंड्रयू विल्किंसन के जवाब में।

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

my_dict.setdefault(key, []).append(item)

यदि कुंजी का मान डिक्शनरी में मौजूद नहीं है, तो सेटडफॉल्ट विधि इसे सेटडेफॉल्ट के दूसरे पैरामीटर पर सेट करेगी। यह एक मानक my_dict [कुंजी] की तरह व्यवहार करता है, कुंजी के लिए मान लौटाता है (जो नया सेट मान हो सकता है)।


वास्तव में पाइथोनिक (अपने जैसे किसी बाहरी व्यक्ति) को क्या दिखता है, किसी भी प्रश्न के कम से कम 3 मान्य उत्तर हैं :)
davka

@davka: ठीक है, तीन उपयोग के मामले लगभग समान हैं, लेकिन अलग-अलग हैं: क) पता करें कि क्या शब्दकोश में कोई गैर-तत्व नहीं है) शब्दकोश से एक मान प्राप्त करें या एक डिफ़ॉल्ट मान का उपयोग करें यदि मूल्य मौजूद नहीं है ग) शब्दकोश से एक मान निकालते हैं और एक डिफ़ॉल्ट संग्रहीत करते हैं यदि मूल्य अभी तक मौजूद नहीं है।
एन डी।

मुझे पता है :) यह एक समालोचना नहीं है, मैं सिर्फ इस तथ्य से
चकित हूं

@ Ryeguy के जवाब के लिए एक टिप्पणी में, स्टुअर्ट वुडवर्ड का सुझाव है "भाषाओं में अपवाद हैंडलिंग में ओवरहेड हमेशा हैश टेबल लुकअप से अधिक परिमाण का एक आदेश है जो निर्धारित करता है कि आइटम मौजूद है या नहीं शब्दकोश में", जबकि आप कह रहे हैं "" शब्दकोश में डुप्लिकेट कुंजी लुकअप से भी बचा जाता है ... यदि लुकअप महंगा है "- क्या किसी के पास कोई माप है जहां अपवाद हैंडलिंग एक डबल कुंजी लुकअप की तुलना में तेज या धीमी है?
माइकल फर्थ

1
@MichaelFirth मैंने पायथन के अपवाद ओवरहेड के लिए एक सरसरी खोज की: stackoverflow.com/questions/2522005/… यह धीमी है, लेकिन बहुत कुछ नहीं। ध्यान रखें कि एक अपवाद को फेंकने की उच्च स्तर की अवधारणा को विभिन्न भाषाओं में बहुत अलग तरीके से संभाला जाता है और आप पेशेवरों और विपक्षों को सामान्य नहीं कर सकते हैं। तो जबकि "अपवाद में 10x ओवरहेड है" जावा के लिए सही हो सकता है, यह पायथन (या स्विफ्ट या अन्य) के लिए नहीं है।
एन डी।

13

Cgoldberg के साथ सहमत हुए। मैं यह कैसे कर सकता हूं:

try:
    dict[key] += 1
except KeyError:
    dict[key] = 1

तो या तो इसे ऊपर के रूप में करें, या डिफ़ॉल्ट डिक्टेट का उपयोग करें जैसा कि दूसरों ने सुझाव दिया है। बयानों का उपयोग न करें। वह पायथन नहीं है।


8
यदि बयान पाइथोनिक नहीं हैं तो कैसे होंगे?
एडम पार्किन

2
मुझे लगता है कि यह एक मामला है जहां पायथन का ईएएफपी सबसे अच्छा तरीका नहीं है। ऊपर दिए गए आपके उदाहरण में डुप्लिकेट कोड है; क्या होगा अगर एक दिन हम चाहते हैं +=2या -=1? आपको दोनों लाइनों को बदलने के लिए याद रखना होगा। यह अब एक तुच्छ चीज की तरह लग सकता है, लेकिन ये एक तरह से बेवकूफ छोटी 'तुच्छ' कीड़े हैं जो आपको काटने के लिए वापस आ सकते हैं।
कैम जैक्सन

3
यह अच्छा लग रहा है और ठीक काम करता है, लेकिन मैं आमतौर पर इसे इस तरह से करने से बचता हूं क्योंकि मुझे लगता है कि भाषाओं में अपवाद हैंडलिंग में ओवरहेड हमेशा हैश टेबल लुकअप से अधिक परिमाण का एक क्रम है जो निर्धारित करता है कि आइटम मौजूद है या नहीं शब्दकोश में है।
स्टुअर्ट वुडवर्ड

11

जैसा कि आप कई उत्तरों से देख सकते हैं, कई समाधान हैं। LBYL का एक उदाहरण (आपके लीप से पहले देखें) अभी तक उल्लेख नहीं किया गया है, has_key () विधि:

my_dict = {}

def add (key):
    if my_dict.has_key(key):
        my_dict[key] += 1
    else:
        my_dict[key] = 1

if __name__ == '__main__':
    add("foo")
    add("bar")
    add("foo")
    print my_dict

6
has_key () 'ऑपरेटर' की तुलना में धीमा है और कम पठनीय है।
अबगन

9
... और यह अजगर 2.6 में हटा दिया गया है और अजगर 3 में हटा दिया गया है
टिम Pietzcker

7

जिस तरह से आप इसे करने की कोशिश कर रहे हैं उसे LBYL कहा जाता है (आप लीप लेने से पहले देखें), चूंकि आप अपने मूल्य को बढ़ाने की कोशिश करने से पहले शर्तों की जांच कर रहे हैं।

दूसरे दृष्टिकोण को ईएएफपी कहा जाता है (माफी मांगना आसान है तो अनुमति)। उस स्थिति में, आप बस संचालन (मूल्य वृद्धि) का प्रयास करेंगे। यदि यह विफल रहता है, तो आप अपवाद को पकड़ते हैं और मान को 1 पर सेट करते हैं। यह (IMO) करने के लिए यह थोड़ा अधिक पायथनिक तरीका है।

http://mail.python.org/pipermail/python-list/2003-May/205182.html


5

थोड़ा देर से लेकिन यह काम करना चाहिए।

my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1

वाह, एक जावा प्रोग्रामर के रूप में, यह एक बहुत ही पागल दिखने वाला निर्माण है। यह एक अजीब तरह से आदेश दिया टर्नरी ऑपरेटर की तरह दिखता है?
forresthopkinsa

5

यह सीधे सवाल का जवाब नहीं दे रहा है, लेकिन मेरे लिए, ऐसा लगता है कि आप संग्रह की कार्यक्षमता चाहते हैं । मुठभेड़

from collections import Counter

to_count = ["foo", "foo", "bar", "baz", "foo", "bar"]

count = Counter(to_count)

print(count)

print("acts just like the desired dictionary:")
print("bar occurs {} times".format(count["bar"]))

print("any item that does not occur in the list is set to 0:")
print("dog occurs {} times".format(count["dog"]))

print("can iterate over items from most frequent to least:")
for item, times in count.most_common():
    print("{} occurs {} times".format(item, times))

इससे आउटपुट उत्पन्न होता है

Counter({'foo': 3, 'bar': 2, 'baz': 1})
acts just like the desired dictionary:
bar occurs 2 times
any item that does not occur in the list is set to 0:
dog occurs 0 times
can iterate over items from most frequent to least:
foo occurs 3 times
bar occurs 2 times
baz occurs 1 times

काउंटर defaultdict(int)कुछ अतिरिक्त कार्यक्षमता के साथ काम करता है, इसलिए यह पूर्ण रूप से पूर्णांक के साथ काम करते समय पूरी तरह से काम करेगा लेकिन आप किसी भी प्रासंगिक व्यवहार को नहीं दिखाते हैं।
तदह मैकडॉनल्ड्स-जेनसेन

4

यहाँ एक-लाइनर है जो मैं हाल ही में इस समस्या को हल करने के लिए आया था। यह सेटडेफ़ॉल्ट शब्दकोश विधि पर आधारित है :

my_dict = {}
my_dict[key] = my_dict.setdefault(key, 0) + 1

0

मैं इसके लिए देख रहा था, यह वेब पर नहीं मिला, फिर कोशिश / त्रुटि के साथ मेरी किस्मत की कोशिश की और इसे पाया

my_dict = {}

if my_dict.__contains__(some_key):
  my_dict[some_key] += 1
else:
  my_dict[some_key] = 1

1
आपको __contains__उत्पादन कोड में उपयोग नहीं करना चाहिए । btw। __contains__उपयोग करने के समान है is
user1767754

1
my_dict.__contains__(some_key)के बराबर है some_key in my_dict, के लिए अधिभार है inऑपरेटर नहींis
Tadhg मैकडॉनल्ड्स-जेन्सेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.