Understanding intersect and difference of dictionaries in python - python

I am new to python and came across this problem as english is not my native language so I am having a little trouble with this problem but wrote my code as of what I understand from this question can anyone tell if I am right and if not please improve my code or give your's
Assume you are given two dictionaries d1 and d2, each with integer keys and integer values. You are also given a function f, that takes in two integers, performs an unknown operation on them, and returns a value.
Write a function called dict_interdiff that takes in two dictionaries (d1 and d2). The function will return a tuple of two dictionaries: a dictionary of the intersect of d1 and d2 and a dictionary of the difference of d1 and d2, calculated as follows:
'''Intersect: The keys to the intersect dictionary
are keys that are common in both d1 and d2.
To get the values of the intersect dictionary,
look at the common keys in d1 and d2 and applythe
functionf to these keys' values -- the value
of the common key in d1 is the first parameterto the
function and the value of the common key in d2
is the second parameter to the function.
Do not implement f inside your dict_interdiff code --
assume it is defined outside.
Difference: a key-value pair in the difference dictionary is
(a) every key-value pair
in d1 whose key appears only in d1 and not in d2 or (b) every
key-value pair in d2 whose
key appears only in d2 and not in d1.'''
Here are two examples:*
'''If f(a, b) returns a + b
d1 = {1:30, 2:20, 3:30, 5:80}
d2 = {1:40, 2:50, 3:60, 4:70, 6:90}
then dict_interdiff(d1, d2)
returns ({1: 70, 2: 70, 3: 90}, {4: 70, 5: 80, 6: 90})
If f(a, b) returns a > b
d1 = {1:30, 2:20, 3:30}
d2 = {1:40, 2:50, 3:60}
then dict_interdiff(d1, d2)
returns ({1: False, 2: False, 3: False}, {})'''
Here is my code :
def dict_interdiff(d1, d2):
a=d1.keys()
b=d2.keys()
c=d1.values()
d=d2.values()
e=()
u={}
f=[]
g=[]
for i in range(max(a,b)):
if a[i]==b[i]:
u=f(a[i],b[i])
elif a[i] not in b:
t=c.find(a[i])
f.append(c[t])
g.append(a[i])
k=dict(zip(g,f))
elif b[i] not in a:
t=c.find(b[i])
f.append(d[t])
g.append(b[i])
k=dict(zip(g,f))
e+(u,)+(k,)
return e
Moreover I cannot check my code because it given to assume that f is defined and I don't know that and hence cannot run in my interpreter

You can do it all using set operations on the dicts:
def dict_interdiff(d1, d2):
# symmetric difference, keys in either d1 or d2 but not both.
sym_diff = d1.viewkeys() ^ d2
# intersection, keys that are common to both d1 and d2.
intersect = d1.viewkeys() & d2
# apply f on values of the keys that common to both dicts.
a = {k: f(d1[k], d2[k]) for k in intersect}
b = {k: d1[k] for k in sym_diff & d1.viewkeys()}
# add key/value pairings from d2 using keys that appear in sym_diff
b.update({k: d2[k] for k in sym_diff & d2.viewkeys()})
return a,b
sym_diff = d1.viewkeys() ^ d2 gets the Symmetric_difference i.e the keys that are in either a or b but not in both.
intersect = d1.viewkeys() & d2 gets the intersection of the keys i.e keys that appear in both d1 and d2.
b = {k: d1[k] for k in sym_diff.viewkeys() & d1} creates a dict of comprising of the keys from d1 that appear in the sym_diff set.
b.update({k: d2[k] for k in sym_diff.viewkeys() & d2}) updates b adding the key/value pairings from d2, using the keys that appear in sym_diff so you end up with a dict b that has all the keys from the sym_diff set and their values.

Seems pretty straightforward, based on the differences.
def dict_interdiff(d1, d2, f):
sameKeys = set(d1.keys()) & set(d2.keys()) # Keys in both dicts
same = dict([(k, f(d1[k],d2[k])) for k in sameKeys]) # f applied
diffKeys = set(d1.keys())^set(d2.keys()) # Keys in single dict
diffs = dict([(k,d1.get(k, d2.get(k))) for k in diffKeys]) # values
return (same,diffs,)
I suppose I should share confirmation it delivered expected results!
>>> dict_interdiff(d1, d2, f)
({1: 70, 2: 70, 3: 90}, {4: 70, 5: 80, 6: 90})

You can always check your code by defining it yourself in the file. Here's my simple implementation:
def dict_interdiff(d1, d2):
'''
d1, d2: dicts whose keys and values are integers
Returns a tuple of dictionaries according to the instructions above
'''
# Your code here
orderedintersect={}
ordereddiff={}
done=d1.copy()
dtwo=d2.copy()
for key in done:
if key in dtwo:
orderedintersect[key]=f(done[key],dtwo[key])
del d1[key]
del d2[key]
d1.update(d2)
for i in sorted(d1.keys()):
ordereddiff[i]=d1[i]
return orderedintersect,ordereddiff
def f(a,b):
return a+b

Related

Compare two dicts and print non-equal values in python

I need to compare dictionary b against a to check whether the keys of b are in a.
If present check the values of a[key]==b[key]. If not equal print the key:value pair of both dictionaries for reference. How can I do that?
a = {'key_1': 1,'key_2': 2, 'key_3': 3}
b = {'key_1': 1,'key_2': 5}
[k for key in b if key in a if b[k]!=a[k]]
I used the above code, but not able to print both the dictionaries keys and value as like
not equal: b[key_2]=5 and a[key_2]=2
I need to compare dictionary b against a to check whether the keys of b are in a. You want to find the intersecting keys and then check their values:
a = {'key_1': 1,'key_2': 2, 'key_3': 3}
b = {'key_1': 1,'key_2': 5}
# find keys common to both
inter = a.keys() & b
diff_vals = [(k, a[k], b[k]) for k in inter if a[k] != b[k]]
# find keys common to both
inter = a.keys() & b
for k,av, bv in diff_vals:
print("key = {}, val_a = {}, val_b = {}".format(k, av, bv))
key = key_2, val_a = 2, val_b = 5
You can use many different set methods on the dict_view objetcs:
# find key/value pairings that are unique to either dict
symmetric = a.items() ^ b.items()
{('key_2', 2), ('key_2', 5), ('key_3', 3)}
# key/values in b that are not in a
difference = b.items() - a.items()
{('key_2', 5)}
# key/values in a that are not in b
difference = a.items() - b.items()
{('key_3', 3), ('key_2', 2)}
# get unique set of all keys from a and b
union = a.keys() | b
{'key_1', 'key_2', 'key_3'}
# get keys common to both dicts
inter = a.keys() & b
{'key_1', 'key_2'}
What you want is likely this:
result = [(k, a[k], b[k]) for k in a if k in b and a[k]!=b[k]]
In other words, "generate a list of tuples composed of the key, the first value and the second, whenever a key in a is also in b and the corresponding values are not equal".
Since the boolean expressions with "and" are failsafe (they evaluate from left to right and stop as soon as a False value is found), you don't have to worry that "b[k]!=a[k]" could raise an exception.
This raises another question: what if the key is in a and not b or vice-versa, e.g. ('car', 2, None) or ('car', None, 2)? Should that also be a valid answer?
I think there is a small error in the code you posted. First, you seem to mix k and key for the same object. Second, you cannot have two if-clauses in a list comprehension, but instead you can combine them with and. Here is how it could look: [k for k in b if k in a and a[k]!=b[k]]
This will produce a list with all the keys for which the values don't match. Given such a key, you can simply use e.g. "a[{k}]={a} and b[{k}]={b}".format(k=k,a=a[k],b=b[k]) to get a human-readable string describing that mismatch. Of couse, if you are only going to create that list of keys to loop over it afterwards (for printing), then there is no need to actually create that list in the first place. Simply iterate directly over the dictionary keys.
This might work
a = {'key_1': 1,'key_2': 2, 'key_3': 3}
b = {'key_1': 1,'key_2': 5}
i=[k for k in b if k in a if b[k]!=a[k]]
if i:
for k in i:
print('not equal:b[',k,']=',b[k],'and a[',k,']=',a[k])
Output
not equal:b[ key_2 ]= 5 and a[ key_2 ]= 2

Operations with multiple dicts

The main questions is how do I have to iterate / indicate correctly to work with two dicts?
I have given two dicts (d1, d2) which I have to compare. If the key i is the same in both, an operation is followed due to a given function. The result goes into another dict (dict1). If either d1 or d2 contains the key i, the value goes in to dict2. The return is a tup = (dict1, dict2). Here is an example.
If f(a, b) returns a + b
d1 = {1:30, 2:20, 3:30, 5:80}
d2 = {1:40, 2:50, 3:60, 4:70, 6:90}
then dict_interdiff(d1, d2) returns ({1: 70, 2: 70, 3: 90}, {4: 70, 5: 80, 6: 90})
I am struggling with the correct way to properly indicate the two dicts d1 and d2. Here is my code:
def h(a, b):
return a > b
d2 = {1:40, 2:50, 3:60, 4:70, 6:90}
d1 = {1:30, 2:20, 3:30, 5:80}
def dict_interdiff(d1, d2):
dict1 = {}
dict2 = {}
for i in d1:
if i in d1 #and d2:
dict1[i] = h(d1[i], d2[i])
else:
dict[i] = d1[i] #or d2[i]
tup = (dict1, dict2)
return tup
Do I have to loop over d1 and d2 (for i in d1 and d2:)? It seems like I have to somehow integrate both given dicts to make the for loop work.
Thanks for any hints!
import itertools
def interdict(d1,d2):
dict1 = {}
dict2 = {}
for i in set(itertools.chain(d1, d2)):
if i in d1 and i in d2:
#whatever
elif i in d1:
#not in d2
else:
#not in d1
set gets rid of duplicates. itertools.chain combines the two lists of keys in the dictionaries
Use itertools.chain to get an iterable of all keys in your dicts.
from itertools import chain
def h(a, b):
return a > b
d2 = {1:40, 2:50, 3:60, 4:70, 6:90}
d1 = {1:30, 2:20, 3:30, 5:80}
def dict_interdiff(d1, d2):
dict1 = {}
dict2 = {}
for key in set(chain(d1, d2)):
if key in d1 and key in d2:
dict1[key] = h(d1[key], d2[key])
else:
dict2[key] = d1.get(key) or d2.get(key)
return dict1, dict2

Comparing Multiple Dictionaries With Specific Values

I have four dictionaries of similar length.
I want to:
get those keys that are matched between the four.
Iterate over certain value in each dictionary which I will compare later and do some arithmetic operations.
I have done that using nested loop (four loops) but that doesn't look efficient at all. I want to make this code more efficient and elegant.
I want to do that without doing nested loop:
d1 = {1:18:[['28','Y','N'],['108','A','M'],...]
d2,d3 and d4 are the same thing expect different values but some will have same keys
for k, v in di1.iteritems():
for v1 in v:
for k2,v2 in di2.iteritems():
for va2 in v2:
if k == k2:
for k3,v3 in di3.iteritems():
for va3 in v3:
if k2 == k3:
for k4,v4 in di4.iteritems():
for va4 in v4:
if k3==k4 and k==k4 and k==k3:
# do some arithmetics on dictionary's values for all four dictionaries
Thanks a lot in advance.
if they have the same keys, then di1.keys() == di2.keys() == di3.keys() == di4.keys().
keys = di1.keys()
for k in keys:
# do something with di1[k] di2[k] di3[k] di4[k]
if they do not all have the keys, build the union set of the keys, and check which dict has each key, using in:
keys = set(di1.keys()) | set(di2.keys()) | set(di3.keys()) | set(di4.keys())
for k in keys:
if k in di1:
# di1 has the key
if k in di2:
# di2 has the key
if k in di1 and k in di2:
# do something with di1[k] and di2[k]
# ...
1) I assume "get those keys that are matched between the four" means you want to find keys that are present in ALL four dictionaries. One way to achieve this is to take the intersection of the four sets of keys.
common_keys = set(d1.keys()) & set(d2.keys()) & set(d3.keys()) & set(d4.keys())
2) Iterate over the common keys and "do some arithmetics on dictionary's values for all four dictionaries":
for key in common_keys:
for dict in [d1, d2, d3, d4]:
# do something with dict[key]...
You can also use list comprehensions if you wish to avoid nested loops, e.g. generate a list of (key, list of tuples) pairs and operate on that later:
common_keys_vals = [(key, [dict[key] for dict in [d1, d2, d3, d4]])
for key in common_keys]

update a set inside a dict comprehension?

I have two dicts, that share the same keys but have distinct values. Each value is a set like this:
d1 = {'a': set(["a","b","c"]), 'b': set(["x","y","c"])}
d2 = {'a': set(["a","b","yu"]), 'b': set(["x","y","ri"])}
I would like to create a new dict, d3 that contains the same keys as d1 and d2, but with values that are the result of update each set of d1[key] with d2[key], I would like to do this inside a dict comprehension, something like:
d3 = {k: d1[k].update(d2[k]) for k in d1}
However, the result of:
d1[k].update(d2[k])
Of course is None, and I get a dict like:
d3 = {'a':None, 'b':None}
Any ideas?
update is the in-place version. The method that returns a new set and leaves the original unchanged is union; alternatively, you can use the | operator
d3 = {k: d1[k].union(d2[k]) for k in d1}
# or
d3 = {k: d1[k] | d2[k] for k in d1}
Is this what you want? I'm not sure
d3 = {k: d1[k] | d2[k] for k in d1}

two dictionaries to make a new one, difficult referencing

This is what my code looks like thus far:
Given dictionaries, d1 and d2, create a new dictionary with the following property: for each entry (a, b) in d1, if there is an entry (b, c) in d2, then the entry (a, c) should be added to the new dictionary.
For example, if d1 is {2:3, 8:19, 6:4, 5:12} and d2 is {2:5, 4:3, 3:9}, then the new dictionary should be {2:9, 6:3}
Associate the new dictionary with the variable  d3
d3 ={}
for i in d1:
for i in d2:
if d1.get(i,default=none) in d2:
d3[d1] = d2.get(i,default = None)
Python can express this beautifully. Too bad it's homework and you probably can't use dict comprehensions or whatever other limitations your "teacher" gives you
>>> d1 = {2:3, 8:19, 6:4, 5:12}
>>> d2 = {2:5, 4:3, 3:9}
>>> d3 = {a:d2[b] for a, b in d1.items() if b in d2}
>>> d3
{2: 9, 6: 3}
For Python2.5 or Python2.6 use a generator expression with dict()
d3 = dict((a, d2[b]) for a, b in d1.items() if b in d2)
For 2.4 see #KP's answer
Or, if you like one-liners:
d3 = dict([(k, d2[v]) for k, v in d1.items() if v in d2])

Categories

Resources