5

I am trying to determine if a specific key and value pair exist in a dictionary; however, if I use the contains or has-key method, it only checks for the key. I need it to check both the key and the specific value. Some background: We have a total of 4 dictionaries: one for A, B, CompareList, and ChangeList. Once A is initialized, I put A's contents into CompareList (I would compare them directly; but A and B are double hash tables. And I've tried all of the methods here; but none of them work for me). So once we put A into CompareList, I compare it with the ObjectAttributes dictionary in B to see if anything changed. So for example, B may have the key,value pairs shape:circle and fill:no. If CompareList had shape:circle and fill:yes, then I want only fill:yes to be ChangeList. The problem lies in the "if attributes.getName() not in self.CompareList:" line. Here is the code; I am running it on Python 2.7.8. Thanks in advance for any help!!

class ObjectSemanticNetwork: def __init__(self): self.ObjectNames = {} self.ObjectAttributes = {} def setName(self, name): self.ObjectNames[name] = self.ObjectAttributes def setData(self, name, attribute): self.ObjectAttributes[name] = attribute def checkData(self, key): print(key) for key, value in self.ObjectAttributes.iteritems(): print(key) print(value) print("\n") class Agent: (self): self.CompareList = {} self.ChangeListAB = {} self.ChangeListCD = {} def addToCompareList(self, name, value): self.CompareList[name] = value def addToChangeListAB(self, name, value): self.ChangeListAB[name] = value def addToChangeListCD(self, name, value): self.ChangeListCD[name] = value def CheckList(self, List, ListName): print '-------------------------',ListName,'--------------------------------' for key, value in List.iteritems(): print(key) print(value) def Solve(self,problem): OSNAB = ObjectSemanticNetwork() for object in problem.getFigures().get("A").getObjects(): for attributes in object.getAttributes(): self.addToCompareList(attributes.getName(), attributes.getValue()) OSNAB.ObjectNames["A"] = OSNAB.setData(attributes.getName(), attributes.getValue()) #OSNAB.checkData("A") self.CheckList(self.CompareList,"CompareList") for object in problem.getFigures().get("B").getObjects(): for attributes in object.getAttributes(): if attributes.getName() not in self.CompareList: self.addToChangeListAB(attributes.getName(), attributes.getValue()) OSNAB.ObjectNames["B"] = OSNAB.setData(attributes.getName(), attributes.getValue()) # OSNAB.checkData("B") self.CheckList(self.ChangeListAB,"ChangeList") OSNCD = ObjectSemanticNetwork() for object in problem.getFigures().get("C").getObjects(): for attributes in object.getAttributes(): OSNCD.ObjectNames["C"] = OSNCD.setData(attributes.getName(), attributes.getValue()) # OSNCD.checkData("C") for object in problem.getFigures().get("1").getObjects(): for attributes in object.getAttributes(): OSNCD.ObjectNames["D"] = OSNCD.setData(attributes.getName(), attributes.getValue()) # OSNCD.checkData("D") return "6" 
6
  • 3
    what's wrong with key in dictionary and dictionary[key] == value? Commented Sep 7, 2014 at 15:14
  • The problem with this way (and I should have specified this earlier) is that because I am doing A LOT of iterations, using an "and" in the if statement would add time. We have to optimize as much as possible; so any additional overhead to an already complicated problem is bad. Thanks for helping. Commented Sep 7, 2014 at 15:37
  • really? creating new try/except stacks (as in accepted answer) is faster in your case than a simple little and operator? I guess the keys almost always already exist in your case or perhaps compilers can optimize it better.. what is the timing difference from your profiling plz - is the improvement in order of magnitudes? Commented Sep 7, 2014 at 15:55
  • 1
    @ElijahPhilpotts: When in doubt, profile. Both key in dictionary and dictionary[key] == value are implemented in C. The additional cost of try-except in a Python level function should make checkKeyValuePairExistence less efficient. Commented Sep 7, 2014 at 15:58
  • @ElijahPhilpotts: I added some timings to my answer. Check it out. Commented Sep 7, 2014 at 16:25

3 Answers 3

12

Use

if key in d and d[key] == value: 

Or (only in Python 3)

if (key, value) in d.items(): 

In Python 3 d.items() returns a Dictionary view object, which supports fast membership testing. In Python 2 d.items() returns a list, which is both slow to create and slow to to test membership. Python 2.7 is a special case where you can use d.viewitems() and get the same thing that you get with d.items() in Python 3.

Edit: In a comment you indicate that for performance reasons you prefer checkKeyValuePairExistence over key in d and d[key] == value. Below are some timings showing that checkKeyValuePairExistence is always slower (by about 2x on my system when the key-value pair is present 16x when it is not). I also tested larger and smaller dictionaries and found little variation in the timings.

>>> import random >>> from timeit import timeit >>> def checkKeyValuePairExistence(dic, key, value): ... try: ... return dic[key] == value ... except KeyError: ... return False ... >>> d = {random.randint(0, 100000):random.randint(0, 100000) for i in range(1000)} >>> setup = 'from __main__ import k, d, v, checkKeyValuePairExistence' >>> test_try_except = 'checkKeyValuePairExistence(d, k, v)' >>> test_k_in_d_and = 'k in d and d[k] == v' >>> k, v = random.choice(d.items()) # to test if found >>> timeit(test_try_except, setup=setup) 0.1984054392365806 >>> timeit(test_k_in_d_and, setup=setup) 0.10442071140778353 >>> k = -1 # test if not found >>> timeit(test_try_except, setup=setup) 1.2896073903002616 >>> timeit(test_k_in_d_and, setup=setup) 0.07827843747497809 
Sign up to request clarification or add additional context in comments.

5 Comments

it might be noteworthy that the not value as 2nd argument of get is there to make non-existing key not equal to None (any other reason?)
@Aprillion: Correct. If the key was not in the dictionary and the value tested for was None, d.get(key) == value would incorrectly evaluate to True.
incorrectly, but sometimes it might be useful - in which case it's better written explicitly as if value == None and key not in d ... to prevent future headaches :)
Thanks for the help. I ended up using something similar to the second method.
@ElijahPhilpotts: if key in d and d[key] == value is such basic idiomatic Python that it doesn't need to be encapsulated in a function named checkKeyValuePairExistence. (But of course it is a matter of taste.)
2

How about this function:

def checkKeyValuePairExistence(dic, key, value): try: return dic[key] == value except KeyError: return False 

If you are using another type of dictionary other then the one python offers (I'm sorry, I couldnt understand from your post if you are using it or not) then let me know and i'll try to give your another solution

Comments

0

Why not just do this:

a = {1:'a', 2:'b'} b = (1, 'a') print b in a.iteritems() # prints True 

4 Comments

-1. This negates one of the major advantages of dictionaries -- efficient membership testing. When the key-value pair is present the average search would need to visit half the items. It would need to search all the items to determine the key-value pair is not found.
A try-except example was already provided. I'm just adding a different example
It's not really "just another example". I believe it is bad answer. Others can disagree and upvote. (Also, I edited a space into your answer because I accidentally upvoted it instead of downvoted it. I couldn't change my vote unless it was edited.)
Hey, it does what OP asked

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.