Reputation: 8143
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?
Upvotes: 0
Views: 136
Reputation: 2564
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
Upvotes: 0
Reputation: 95642
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.
Upvotes: 6
Reputation: 717
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}
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,
Upvotes: 0
Reputation: 229
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
-----
Upvotes: 1
Reputation: 608
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
Upvotes: 0
Reputation: 1281
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.
Upvotes: 0