two dictionaries to make a new one, difficult referencing - python

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])

Related

Concatenate dictionaries using values in different dictionaries

I have two dictionaries. Like this:
d1 = {A: 1, B:2, C:3}
d2 = {1: xx, 2:xxx, 3:xxxx}
I wrote a code to compare both:
for k, v in d1.iteritems():
for l, m in d2.iteritems():
if l == v:
print k+'\t'+v+'\t'+m
And print as a table like this:
A 1 xx
B 2 xxx
C 3 xxxx
Suggestions like to create a new_dictionary is accepted.
for k, v in d1.iteritems():
if v in d2:
print('{}\t{}\t{}'.format(k, v, d2[v]))
"Suggestions like to create a new_dictionary is accepted."
print {key : [d1[key], d2[d1[key]]] for key in d1 if d1[key] in d2 }
for k, v in d1.items():
print(k, v, d2[v])
This is how to do it in Python 3.
Try this : simple and easy.
for i in d1:
if d1[i] in d2:
print i,d1[i],d2[d1[i]]

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

Understanding intersect and difference of dictionaries in 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

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}

How can I perform set operations on Python dictionaries?

While it is incredibly useful to be able to do set operations between the keys of a dictionary, I often wish that I could perform the set operations on the dictionaries themselves.
I found some recipes for taking the difference of two dictionaries but I found those to be quite verbose and felt there must be more pythonic answers.
tl;dr Recipe: {k:d1.get(k, k in d1 or d2[k]) for k in set(d1) | set(d2)} and | can be replaced with any other set operator.
Based #torek's comment, another recipe that might be easier to remember (while being fully general) is: {k:d1.get(k,d2.get(k)) for k in set(d1) | set(d2)}.
Full answer below:
My first answer didn't deal correctly with values that evaluated to False. Here's an improved version which deals with Falsey values:
>>> d1 = {'one':1, 'both':3, 'falsey_one':False, 'falsey_both':None}
>>> d2 = {'two':2, 'both':30, 'falsey_two':None, 'falsey_both':False}
>>>
>>> print "d1 - d2:", {k:d1[k] for k in d1 if k not in d2} # 0
d1 - d2: {'falsey_one': False, 'one': 1}
>>> print "d2 - d1:", {k:d2[k] for k in d2 if k not in d1} # 1
d2 - d1: {'falsey_two': None, 'two': 2}
>>> print "intersection:", {k:d1[k] for k in d1 if k in d2} # 2
intersection: {'both': 3, 'falsey_both': None}
>>> print "union:", {k:d1.get(k, k in d1 or d2[k]) for k in set(d1) | set(d2)} # 3
union: {'falsey_one': False, 'falsey_both': None, 'both': 3, 'two': 2, 'one': 1, 'falsey_two': None}
The version for union is the most general and can be turned into a function:
>>> def dict_ops(d1, d2, setop):
... """Apply set operation `setop` to dictionaries d1 and d2
...
... Note: In cases where values are present in both d1 and d2, the value from
... d1 will be used.
... """
... return {k:d1.get(k,k in d1 or d2[k]) for k in setop(set(d1), set(d2))}
...
>>> print "d1 - d2:", dict_ops(d1, d2, lambda x,y: x-y)
d1 - d2: {'falsey_one': False, 'one': 1}
>>> print "d2 - d1:", dict_ops(d1, d2, lambda x,y: y-x)
d2 - d1: {'falsey_two': None, 'two': 2}
>>> import operator as op
>>> print "intersection:", dict_ops(d1, d2, op.and_)
intersection: {'both': 3, 'falsey_both': None}
>>> print "union:", dict_ops(d1, d2, op.or_)
union: {'falsey_one': False, 'falsey_both': None, 'both': 3, 'two': 2, 'one': 1, 'falsey_two': None}
Where items are in both dictionaries, the value from d1 will be used. Of course we can return the value from d2 instead by changing the order of the function arguments.
>>> print "union:", dict_ops(d2, d1, op.or_)
union: {'both': 30, 'falsey_two': None, 'falsey_one': False, 'two': 2, 'one': 1, 'falsey_both': False}
EDIT: The recipes here don't deal correctly with False values. I've submitted another improved answer.
Here are some recipes I've come up with:
>>> d1 = {'one':1, 'both':3}
>>> d2 = {'two':2, 'both':30}
>>>
>>> print "d1 only:", {k:d1.get(k) or d2[k] for k in set(d1) - set(d2)} # 0
d1 only: {'one': 1}
>>> print "d2 only:", {k:d1.get(k) or d2[k] for k in set(d2) - set(d1)} # 1
d2 only: {'two': 2}
>>> print "in both:", {k:d1.get(k) or d2[k] for k in set(d1) & set(d2)} # 2
in both: {'both': 3}
>>> print "in either:", {k:d1.get(k) or d2[k] for k in set(d1) | set(d2)} # 3
in either: {'both': 3, 'two': 2, 'one': 1}
While the expressions in #0 and #2 could be made simpler, I like the generality of this expression which allows me to copy and paste this recipe everywhere and simply change the set operation at the end to what I require.
Of course we can turn this into a function:
>>> def dict_ops(d1, d2, setop):
... return {k:d1.get(k) or d2[k] for k in setop(set(d1), set(d2))}
...
>>> print "d1 only:", dict_ops(d1, d2, lambda x,y: x-y)
d1 only: {'one': 1}
>>> print "d2 only:", dict_ops(d1, d2, lambda x,y: y-x)
d2 only: {'two': 2}
>>> import operator as op
>>> print "in both:", dict_ops(d1, d2, op.and_)
in both: {'both': 3}
>>> print "in either:", dict_ops(d1, d2, op.or_)
in either: {'both': 3, 'two': 2, 'one': 1}
>>> print "in either:", dict_ops(d2, d1, lambda x,y: x|y)
in either: {'both': 30, 'two': 2, 'one': 1}
This is an old question, but I'd like to highlight my ubelt package (https://github.com/Erotemic/ubelt), which contains a solutions to this problem.
I'm not sure why PEP584 only added union and no other set operations to dictionaries. I'll need to look into it more to see if there is any existing rational for why Python dictionaries do not contain these methods by default (I imagine there must be, I don't see how the devs could not be aware of set operations on dictionaries).
But to the point. Ubelt implements these functions for core dictionary set operations:
ubelt.dict_diff - analog of set.difference
ubelt.dict_union - analog of set.union
ubelt.dict_isect - analog of set.intersection
I hope someday these or something similar are added to Python dictionaries themselves.
Here are some more:
Set addition d1 + d2
{key: value for key, value in d1.items() + d2.items()}
# here values that are present in `d1` are replaced by values in `d2`
Alternatively,
d3 = d1.copy()
d3.update(d2)
Set difference d1 - d2
{key: value for key, value in d1.items() if key not in d2}

Categories

Resources