|
|||||||
Check if a given key already exists in a dictionary
Время создания: 16.07.2018 10:48
Текстовые метки: python check key dictionary
Раздел: Python
Запись: Velonski/mytetra-database/master/base/1531720089iyj5v4ho8g/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
I wanted to test if a key exists in a dictionary before updating the value for the key. I wrote the following code: if 'key1' in dict.keys(): print "blah" else: print "boo" I think this is not the best way to accomplish this task. Is there a better way to test for a key in the dictionary? python dictionary shareimprove this question edited May 2 '13 at 6:45 bluish 13k1590143 asked Oct 21 '09 at 19:05 Mohan Gulati 11.4k51720 20 Calling dict.keys() creates a list of keys, according to the documentation docs.python.org/2/library/stdtypes.html#dict.keys but I'd be surprised if this pattern wasn't optimised for, in a serious implementation, to translate to if 'key1' in dict:. – Evgeni Sergeev Aug 12 '13 at 8:51 5 So I finally found out why many of my Python scripts were so slow :) :(. That's because I've been using x in dict.keys() to check for keys. And that happened because the usual way to iterate over keys in Java is for (Type k : dict.keySet()), this habit causing for k in dict.keys() to feel more natural than for k in dict (which should still be fine in terms of performance?), but then checking keys becomes if k in dict.keys() too, which is a problem... – Evgeni Sergeev Aug 12 '13 at 8:58 4 @EvgeniSergeev if k in dict_: tests for presence of k in the KEYS of dict_, so you still don't need dict_.keys(). (This has bit me, as it reads to me like its testing for a value in dict. But it isn't.) – ToolmakerSteve Dec 16 '13 at 23:34 1 @ToolmakerSteve That's right, but not only do you not need it, it's not a good practice. – Evgeni Sergeev Dec 17 '13 at 1:51 15 Try "key in dict" – marcelosalloum Jun 26 '14 at 17:18 add a comment 19 Answers active oldest votes up vote 2201 down vote accepted in is the intended way to test for the existence of a key in a dict. d = dict() for i in xrange(100): key = i % 10 if key in d: d[key] += 1 else: d[key] = 1 If you wanted a default, you can always use dict.get(): d = dict() for i in xrange(100): key = i % 10 d[key] = d.get(key, 0) + 1 ... and if you wanted to always ensure a default value for any key you can use defaultdict from the collections module, like so: from collections import defaultdict d = defaultdict(lambda: 0) for i in xrange(100): d[i % 10] += 1 ... but in general, the in keyword is the best way to do it. shareimprove this answer answered Oct 21 '09 at 19:10 Chris B. 41.3k1879113 50 I usually just use get if I'm going to be pulling the item out of the dictionary anyway. No sense in using in and pulling the item out of the dictionary. – Jason Baker Oct 21 '09 at 19:12 45 I fully agree. But if you only need to know if a key exists, or you need to distinguish between a case where the key is defined and a case where you are using a default, in is the best way of doing it. – Chris B. Oct 21 '09 at 19:16 4 Reference for this answer is at the python docs – enkash Jan 28 '15 at 5:54 14 get is a bad test if the key is equivalent to "False", like 0 for example. Learned this the hard way :/ – Sebastien Feb 9 '16 at 21:06 2 I can't agree that this a complete answer as it doesn't mention that 'try'-'except' will be the fastest when number of key fails is sufficiently small. See this answer below: stackoverflow.com/a/1602945/4376643 – Craig Hicks Oct 5 '17 at 1:18 show 3 more comments up vote 1076 down vote You don't have to call keys: if 'key1' in dict: print "blah" else: print "boo" That will be much faster as it uses the dictionary's hashing as opposed to doing a linear search, which calling keys would do. shareimprove this answer edited May 23 '17 at 12:34 Community♦ 11 answered Oct 21 '09 at 19:06 Jason Baker 99.6k102322479 5 That is great. I was under the impression that it would internally still traverse the list of keys, but I see this works more like testing membership in a set. – Mohan Gulati Oct 21 '09 at 19:20 34 @Mohan Gulati: You understand that a dictionary is a hashtable of keys mapped to values, right? A hashing algorithm converts the key to an integer and the integer is used to find a location in the hash table that matches. en.wikipedia.org/wiki/Hash_table – hughdbrown Oct 22 '09 at 2:31 2 @Charles Addis, from experience working with around half a million keys you get at least 10x performance boost when writing "key in dict" instead of "key in dict.keys()". PEP and Zen also states that you should ignore them in case they are bad for your project. – ivan_bilan Jun 20 '16 at 11:25 4 ivan_bilan -- I just ran my own benchtest on this... On half a million keys, if key in d1 took 0.17265701293945312 seconds. Calling if key in d1.keys() took 0.23871088027954102 -- this is the classic definition of a micro-optimization. Saving 0.07884883880615234 seconds is not a performance boost. – Charles Addis Jun 20 '16 at 15:33 2 @Eli Just for you I've created a test you can run yourself. The results may astonish you. For dicts with ~50,000 keys, not calling keys() gives you .01 second computational benefit. For ~500,000 keys, not calling keys() gives you .1 second benefit. For ~5,000,000 keys, not calling keys() is .4 seconds faster, but for 50,000,000 keys CALLING keys() IS 3 SECONDS FASTER! – Charles Addis Sep 6 '16 at 19:48 show 9 more comments up vote 226 down vote You can test for the presence of a key in a dictionary, using the in keyword: d = {'a': 1, 'b': 2} 'a' in d # <== evaluates to True 'c' in d # <== evaluates to False A common use for checking the existence of a key in a dictionary before mutating it is to default-initialize the value (e.g. if your values are lists, for example, and you want to ensure that there is an empty list to which you can append when inserting the first value for a key). In cases such as those, you may find the collections.defaultdict() type to be of interest. In older code, you may also find some uses of has_key(), a deprecated method for checking the existence of keys in dictionaries (just use key_name in dict_name, instead). shareimprove this answer edited Jun 27 '16 at 23:12 answered Oct 21 '09 at 19:16 Michael Aaron Safyan 73.9k12108181 44 dict.has_key(key) has been deprecated in favor of key in dict – David Locke Oct 21 '09 at 19:28 4 Technically, has_key is deprecated for Python 2.x+ (not merely for 3.0+). That is, new code is recommended to not use it, even when writing in Python 2.x. (Because it is a feature known to be going away in future versions, and there is a perfectly good substitute to use instead.) What happens in 3.0 is that it is removed completely. – ToolmakerSteve Dec 16 '13 at 23:19 @ToolmakerSteve You are of course correct and I updated the answer to reflect that. :) – kqr Nov 6 '14 at 13:02 1 Wanted to share that (using Python 2.7) the run time of something I just wrote, basing heavily on dicts, was 363.235070 using "key in dict.keys()" and drastically went down to 0.260186 solely by removing the call for "keys()" – Ido_f Jan 26 '15 at 18:15 @Ido_f please post your benchmarks, as my benchmarks almost no difference in 3.5 and 2.7 – Charles Addis Jun 21 '16 at 21:33 show 1 more comment up vote 73 down vote You can shorten this: if 'key1' in dict: ... However, this is at best a cosmetic improvement. Why do you believe this is not the best way? shareimprove this answer answered Oct 21 '09 at 19:06 Greg Hewgill 632k1339881141 76 This is much more than a cosmetic improvement. The time to find a key using this method is O(1) whereas calling keys would generate a list and be O(n). – Jason Baker Oct 21 '09 at 19:08 4 The O(1) does not seem quite right. Are you sure it's not something like O(log n)? – spectras Aug 22 '15 at 18:08 3 It's the complexity of a single dict lookup, which is on average O(1) and at worst O(n). .list() will always be O(n). wiki.python.org/moin/TimeComplexity – Leo Tindall Oct 28 '15 at 0:18 add a comment up vote 40 down vote I would recommend using the setdefault method instead. It sounds like it will do everything you want. >>> 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} shareimprove this answer answered Oct 21 '09 at 19:07 David Berger 7,60332947 8 What does setdefault have to do with the OP's question? – hughdbrown Oct 21 '09 at 19:11 12 @hughdbrown "I wanted to test if a key exists in a dictionary before updating the value for the key." Sometimes posts include code that generate a flurry of responses to something that's not quite the original goal. To accomplish the goal stated in the first sentence, setdefault is the most effective method, even though it's not a drop-in replacement for the sample code posted. – David Berger Oct 21 '09 at 19:14 3 This is the superior answer because it satisfies OP's goal instead of just giving the technically correct answer. See: nedbatchelder.com/blog/201207/… – Niels Bom Jul 24 '12 at 13:07 +1 for an informative answer, that taught me something. However, whether it is the best solution depends on what the coder has in mind; e.g. the meaning of "before updating the value of the key". Maybe he's going to throw an exception if it is not present (== no permission to add new keys). Maybe its a dictionary of counts, and he's going to add 1 to the existing count, in which case `d[key] = d.get(key, 0) + 1' is the cleanest solution (as Chris shows, after your answer was written). (I only bother mentioning this, in case future readers come here, with different tasks in mind.) – ToolmakerSteve Dec 16 '13 at 23:42 @NielsBom ... IMHO setdefault is only the superior solution when an existing entry should not be overwritten. (An important case, but not the only reason to be testing existence of a key.) – ToolmakerSteve Dec 16 '13 at 23:46 show 1 more comment up vote 34 down vote For additional info on speed execution of the accepted answer's proposed methods (10m loops): 'key' in mydict elapsed time 1.07 sec mydict.get('key') elapsed time 1.84 sec mydefaultdict['key'] elapsed time 1.07 sec Therefore using in or defaultdict are recommended against get. shareimprove this answer answered May 29 '15 at 11:06 Wtower 9,29096155 4 get is in essence the combination of bullet points 1 and 3.. – scape Jun 11 '15 at 23:02 2 totally agree that get's 1.84s is < 1.07*2 ;-P – Paul Rigor Jun 15 '17 at 16:59 add a comment up vote 17 down vote Dictionary in python has a get('key', default) method. So you can just set a default value in case there is no key. values = {...} myValue = values.get('Key', None) shareimprove this answer edited Mar 23 at 18:51 Derlin 5,82621432 answered Mar 1 '17 at 9:03 mafonya 1,2841318 add a comment up vote 15 down vote For checking you can use has_key() method if dict.has_key('key1'): print "it is there" If you want a value then you can use get() method a = dict.get('key1', expeced_type) If you want a tuple or list or dictionary or any string as a default value as return value, then use get() method a = dict.get('key1', {}).get('key2', []) shareimprove this answer edited Jun 27 '16 at 6:41 abarisone 2,79692137 answered Sep 10 '15 at 18:37 Debabrata 423512 4 .get and has_key have already been suggested in answers years before yours, has_key has also been removed in python3 – Padraic Cunningham Dec 14 '15 at 19:58 add a comment up vote 14 down vote What about using EAFP (easier to ask forgiveness than permission): try: blah = dict["mykey"] # key exists in dict except KeyError: # key doesn't exist in dict See other SO posts: Using try vs if in python or Checking for member existence in Python shareimprove this answer edited May 10 at 19:22 Surest Texas 411419 answered Feb 6 '14 at 16:08 HungryArthur 470615 7 Try/except may be more expensive if it's likely that the key often doesn't exist. From the post you referenced: "[I]f you expect that 99 % of the time result will actually contain something iterable, I'd use the try/except approach. It will be faster if exceptions really are exceptional. If result is None more than 50 % of the time, then using if is probably better.[...][A]n if statement always costs you, it's nearly free to set up a try/except block. But when an Exception actually occurs, the cost is much higher." stackoverflow.com/a/1835844/1094092 – billrichards Aug 19 '14 at 20:07 8 Instead of a bare catch I'd specify except KeyError here. – shuttle87 Jul 31 '15 at 14:40 add a comment up vote 13 down vote Just an FYI adding to Chris. B (best answer): d = defaultdict(int) Works as well; the reason is that calling int() returns 0 which is what defaultdict does behind the scenes (when constructing a dictionary), hence the name "Factory Function" in the documentation. shareimprove this answer answered May 19 '13 at 18:12 Mauricio Morales 705810 1 (I gave you the +1, because Chris' defaultdict(lambda: 0) seemed obscure to me. saying "this is a dictionary of int's, so they start with the default value of an int, e.g. int() e.g. 0" I like.) – ToolmakerSteve Dec 17 '13 at 0:03 2 If you're creating a dictionary of counts, you should be using Counter (assuming Python 2.7). And I used defaultdict(lambda: 0) instead of defaultdict(int) because I think it's clearer what's going on; the reader doesn't need to know you get 0 if you call int() without arguments. YMMV. – Chris B. Feb 3 '14 at 19:35 add a comment up vote 13 down vote Using ternary operator: message = "blah" if 'key1' in dict else "booh" print(message) shareimprove this answer answered Aug 18 '17 at 22:58 Charitoo 702717 add a comment up vote 11 down vote You can use the has_key() method: if dict.has_key('xyz')==1: #update the value for the key else: pass Or the dict.get method to set a default value if not found: mydict = {"a": 5} print mydict["a"] #prints 5 print mydict["b"] #Throws KeyError: 'b' print mydict.get("a", 0) #prints 5 print mydict.get("b", 0) #prints 0 shareimprove this answer edited Nov 7 '14 at 22:03 Eric Leschinski 77.9k35307257 answered May 9 '13 at 10:17 wan kenobi 16913 15 .has_key() has been deprecated; you should use in as shown in other answers. – Brad Koch May 11 '13 at 16:50 9 BTW, I recommend reading ALL existing answers to an OLD question, before answering it. This answer added nothing, since the suggestion already existed in Michael's answer, from '09. (I don't mean to discourage an attempt to add something useful to a discussion. Keep trying.) – ToolmakerSteve Dec 16 '13 at 23:58 2 Wan Kenobi Please put @brad-kock comment on top. Indeed the answed has its own value but is not recommendable (not available atleast on Python 3.5.2). – Kuldeep Singh Dhaka Aug 20 '16 at 19:14 add a comment up vote 11 down vote The ways in which you can get the results are: if your_dict.has_key(key) Removed in Python 3 if key in your_dict try/except block Which is better is dependent on 3 things: Does the dictionary 'normally has the key' or 'normally does not have the key'. Do you intend to use conditions like if...else...elseif...else? How big is dictionary? Read More: http://paltman.com/try-except-performance-in-python-a-simple-test/ Use of try/block instead of 'in' or 'if': try: my_dict_of_items[key_i_want_to_check] except KeyError: # Do the operation you wanted to do for "key not present in dict". else: # Do the operation you wanted to do with "key present in dict." shareimprove this answer answered Dec 21 '16 at 7:05 Bishwas Mishra 528416 add a comment up vote 6 down vote print dict.get('key1', 'blah') Won't print boo for the values in the dict, but accomplishes the goal by printing the value of key1 to confirm it's existence instead. shareimprove this answer answered Jul 15 '15 at 18:55 gounc86 8314 add a comment up vote 3 down vote Python dictionary has the method called __contains__. This method will return True if the dictionary has the key else returns False. >>> temp = {} >>> help(temp.__contains__) Help on built-in function __contains__: __contains__(key, /) method of builtins.dict instance True if D has a key k, else False. shareimprove this answer answered Apr 26 '17 at 11:02 Siva Gnanam 3642421 2 It is very bad practice to call __contains__ directly. The correct way of doing it, is to use in operator, which is the containment check that invokes the __contains__ function. – user1767754 Nov 14 '17 at 18:21 add a comment up vote 2 down vote Well.. You will be familiar that searching a element's existence in a list or data means going through everything (at least for unordered list e.g dict.keys ).So Instead using Exception and Errors that arise normally we can avoid that complexity... d={1:'a',2:'b'} try: needed=d[3] print(needed) except: print("Key doesnt exist") shareimprove this answer answered Dec 9 '17 at 11:55 Seenivasan 5631613 add a comment up vote 0 down vote Easiest one is if you know which key(key name) is to look for: # suppose your dictionary is my_dict = {'foo': 1, 'bar': 2} # check if a key is there if 'key' in my_dict.keys(): # it will evaluates to true if that key is present otherwise false. # do something or you can also do simply as: if 'key' in my_dict: # it will evaluates to true if that key is present otherwise false. # do something shareimprove this answer answered Jun 13 '16 at 5:44 Tasneem Haider 4816 3 Repetition of the answer. This is not encouraged here. Please read through the already existing answers and ensure that you are not repeating the same answer. – Arun Thundyill Saseendran Aug 7 '17 at 10:49 add a comment up vote 0 down vote I use the try/except; if an exception is throwed, than the key aren't present at the dictionary. example: st = 'sdhfjaks' d = {} try: print d['st'] except Exception, e: print 'Key not in the dictionary' shareimprove this answer answered Feb 7 at 22:02 Leonardo Maffei 6119 add a comment up vote -1 down vote Why not just use the has_key() method. a = {} a.has_key('b') => #False a['b'] = 8 a.has_key('b') => #True shareimprove this answer answered Jul 9 at 18:36 wmorris 103 This is a duplicate of other answers here. Please read the entire topic first before posting an answer. Also as mentioned in other answers: dict.has_key(key) has been deprecated in favor of key in dict. – nijm Jul 9 at 18:55 |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|