0

I have two dictionaries and I want to compare the values of the corresponding keys. For example, if I have

dict1 = {'a':1, 'b':0, 'c':3}
dict2 = {'a':0, 'b':0, 'c':4}

then this should return False because dict2 can't have a corresponding value larger than that of dict11 (it was okay in dict2 that 'a' had a smaller value than that of dict1, but not okay that 'c' in dict2 had value larger than that of dict1).

Also it is not allowed if dict2 has a value that is not listed in dict1. For instance:

dict1 = {'a':1, 'b':0, 'c':3}
dict2 = {'a':0, 'b':0, 'd':2}

(But it is okay if dict1 has values that dict2 does not). In other words, dict2 has to be a subset of dict1 in regards to both keys and values.

As soon as the code catches one of these violations, I want to immediately stop everything from running and just return False.

This is what I tried:

condition = True #True by default
for letter in dict2:
    if dict2[letter] > dict1[letter] or dict1[letter] == None: 
        condition = False
        break
    break

But I get a KeyError when I run into a key that's listed in dict1 and not in dict2.

How do I fix this?

1
  • 1
    Use try-except statements. Commented Mar 26, 2015 at 11:27

6 Answers 6

6

I think you are looking for something like this:

condition = all(k in dict1 and dict2[k] <= dict1[k] for k in dict2)

You asked in the comments how to read this. That's difficult to answer because not everyone would look at it the same way. Perhaps if I tell you how I got to that expression it may help.

I read your question as saying "every key in dict2 must be in dict1, and the value in dict2 must not be greater than the value from dict1", which I re-expressed as "for all k in dict2, k in dict1 and dict2[k] <= dict1[k]" which seemed a clear case for the all() function, and the for move to the end.

Sign up to request clarification or add additional context in comments.

1 Comment

how would you read this? this is like list comprehension. I always struggle figuring out what it's really doing.
1

Here is a simple approach that avoids using try except. I also included a couple test cases, all of the comparison is in compare_2lt1.

# Set 1 violates the comparison in key 'c', too large
dict1_1 = {'a':1, 'b':0, 'c':3}
dict2_1 = {'a':0, 'b':0, 'c':4}

# Set 2 violates the comparison in key 'd', doesn't exist
dict1_2 = {'a':1, 'b':0, 'c':3}
dict2_2 = {'a':0, 'b':0, 'c':2, 'd':5}

# Set 3 is True
dict1_3 = {'a':1, 'b':0, 'c':3}
dict2_3 = {'a':0, 'b':0, 'c':2}

def compare_2lt1(d1, d2):
    for key in d2:
        if key in d1 and d1[key] >= d2[key]:
            continue
        else:
            return False
    return True

def test(d1, d2):
    print d1
    print d2
    print compare_2lt1(d1, d2)
    print "-----"


test(dict1_1, dict2_1)
test(dict1_2, dict2_2)
test(dict1_3, dict2_3)

Output:

{'a': 1, 'c': 3, 'b': 0}
{'a': 0, 'c': 4, 'b': 0}
False
-----
{'a': 1, 'c': 3, 'b': 0}
{'a': 0, 'c': 2, 'b': 0, 'd': 5}
False
-----
{'a': 1, 'c': 3, 'b': 0}
{'a': 0, 'c': 2, 'b': 0}
True
-----

Comments

0

You may also want to use a defaultdict instead if a 'regular' dict: https://docs.python.org/2/library/collections.html

It just returns false if the key is not found, and doesn't throw an error.

Comments

0

Try modifying to

condition = True #True by default
for letter in dict2:
    if letter not in dict1.keys() or dict2[letter] > dict1[letter]: 
        condition = False
        break
    break

Comments

0

you are getting keyError, because there is no value mapped for a key which is not there in the dictionary, so it will give keyError instead of taking the uninitialized key value as 'None' as you are checking inside for loop:

if dict2[letter] > dict1[letter] or dict1[letter] == None:

@Duncan has written a great answer in single line comprehension, I am just trying to rewrite it as you attempted it,,

d1 = { 'a' = 1,'b' = 2, 'c'= 3}
d2 = { 'a' = 2,'b' = 3, 'd'= 4}

key 'd' is not there in d1 so, it should return False

 condition = True
    for key in d2.keys():
        if not (key in d1.keys() and d2[key] > d1[key]):
            condition = False
            break

now when you look for condition its value would be False,

Comments

0

Is it what you want ?

#Value in dict2 greater than value in dict1 for same key ?
condition1 = sum([dict2[a] > dict1[a] for a in dict2 if a in dict1]) == 0

#keys in dict2 not in dict1
condition2 = [a for a in dict2 if a not in dict1] == []

#The two conditions
condition =  condition1 and condition2 

#Test
if condition:
    print True
print False

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.