Merge dictionaries and add values - python

I have several dictionaries which I'd like to combine such that if a key is in multiple dictionaries the values are added together. For example:
d1 = {1: 10, 2: 20, 3: 30}
d2 = {1: 1, 2: 2, 3: 3}
d3 = {0: 0}
merged = {1: 11, 2: 22, 3: 33, 0: 0}
What is the best way to do this in Python? I was looking at defaultdict and trying to come up with something. I'm using Python 2.6.

using a defaultdict:
>>> d = defaultdict(int)
>>> for di in [d1,d2,d3]:
... for k,v in di.items():
... d[k] += v
...
>>> dict(d)
{0: 0, 1: 11, 2: 22, 3: 33}
>>>

With the very most python standard functions and libraries:
dlst = [d1, d2, d3]
for i in dlst:
for x,y in i.items():
n[x] = n.get(x, 0)+y
Instead of using if-else checks, using dict.get with default value 0 is simple and easy.

without importing anything. .
d4={}
for d in [d1,d2,d3]:
for k,v in d.items():
d4.setdefault(k,0)
d4[k]+=v
print d4
output:
{0: 0, 1: 11, 2: 22, 3: 33}

Related

convert a normal sequence dictionary into reversed triply ordered dictionary

I want to convert my dictionary to a triply ordered reversed dictionary.
my dictionary is {1: 1, 3: 3, 5: 6, 6: 6}
I have already tried using nested dictionaries, but i am not sure how to get the required output.
Dict1 = list(Dict)
Dict2['Dict1'] = Dict
print(Dict2)
The output should be {1: {1: [1], 3: [3]}, 2: {6: [5, 6]}}
if i define a different dictionary, i should get different triply ordered dictionary.
Can someone please help me with this?
from collections import defaultdict
orig_d = {1: 1, 3: 3, 5: 6, 6: 6}
new_d = defaultdict(list)
for k, v in orig_d.items():
new_d[v].append(k)
final_d = defaultdict(dict)
for cnt, (k, v) in sorted((len(v), (k, v)) for k, v in new_d.items()):
final_d[cnt][k] = v
print(dict(final_d))
Prints:
{1: {1: [1], 3: [3]}, 2: {6: [5, 6]}}

Map a dictionary on a list of dictionaries

I have a dictionary Items
Items = {1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 3, 7: 4, 8: 5}
I want to map the values of Items on a list of dictionaries named loaded
loaded = [{6: [4, 1, 3]}, {1: [5]}, {10: [8, 6]}, {6: [7]}, {2: [2]}]
such that I get this as my outcome:
u_loaded = [{6: [2, 1, 2]}, {1: [2]}, {10: [5, 3]}, {6: [4]}, {2: [2]}]
I tried running loops and replacing the values if a match is found but it's not working
for i in loaded_list:
for k,v in i.items():
for j in v:
for a,b in pid_itemid_dic.items():
if j==a:
j=b
u_loaded = [{k:[Items[a] for a in v] for k,v in l.items()} for l in loaded]
print(u_loaded)
Output
[{6: [2, 1, 2]}, {1: [2]}, {10: [5, 3]}, {6: [4]}, {2: [2]}]
One step at a time, you can approach it in the following manner.
loaded = [{6: [4, 1, 3]}, {1: [5]}, {10: [8, 6]}, {6: [7]}, {2: [2]}]
Items = {1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 3, 7: 4, 8: 5}
u_loaded = [{k: [Items[val] for val in v] for k,v in d.items()} for d in loaded]
For an Explanation of 1 liner, we can open it up:
u_loaded = [] #stores the list of dicts
for d in loaded:
u_d = {} #create empty result dict
for k,v in d.items():
u_d[k] = [Items[val] for val in v] #for every value, take the corresponding mapping result from loaded
u_loaded.append(u_d) #append the dictionary to the result list
Output:
[{6: [2, 1, 2]}, {1: [2]}, {10: [5, 3]}, {6: [4]}, {2: [2]}]
You can use a simple list comprehension:
result = [{k: [Items[v] for v in l] for k, l in d.items()} for d in loaded]
print(result)
Output:
[{6: [2, 1, 2]}, {1: [2]}, {10: [5, 3]}, {6: [4]}, {2: [2]}]
This is equivalent to the following for loop:
result = []
for d in loaded:
new_sub_dict = {}
for k, l in d.items():
new_sub_list = []
for v in l:
new_sub_list.append(Items[v])
new_sub_dict[k] = new_sub_list
result.append(new_sub_dict)
You may want to avoid loops in order to adopt a Pythonic style. What you would like to do can be achieved in just one line:
u_loaded = [{k: [Items[i] for i in v] for k, v in d.items()} for d in loaded]
It is using list comprehension to loop over all dictionaries in loaded. And then, it follows a loop over the dictionaries keys k and values v to reconstruct the dictionary you want to create.

How to check if at least one key in dictionary exists as a value in another dictionary in Python?

I am creating a function that accepts a dictionary1 and checks if any of the keys exists as a value dictionary2.
I have tried using the dictionary2.isdisjoint(dictionary1) but this is effective for only checking keys-keys.
How can I check key to value in Python?
Not sure if this is really a big enough task to put into a separate function, but anyway, here's an example using the any() keyword:
if any(k in d2.values() for k in d1.keys()):
# do stuff
If the below statement returns True (it will return common values) then:
set(dictionary1.keys()) & set(dictionary2.values())
Explanation:
dictionary1.keys() will give the list of keys in dictionary1
dictionary2.values() will give the list of values in dictionary2
Convert these two to set and if they have common values, you will end
up with the common values between the two.
dictionary1 = {1:2, 2:3, 3:4}
dictionary2 = {2:1, 2:3, 3:4}
print set(dictionary1.keys()) & set(dictionary2.values())
Output:
set([3])
This isn't an operation that is built-in. You would need to write logic to do it yourself. You seem to be using python 3, so something like the below might work
>>> x = dict.fromkeys([0, 5, 10])
>>> y = {x: x for x in range(5)}
>>> print(x.keys().isdisjoint(y.values()))
False
>>> x.pop(0)
>>> print(x.keys().isdisjoint(y.values()))
True
d = {'1': 'one', '3': 'three', '2': 'two', '5': 'five', '4': 'four'}
d2 = {'5': 'five', '6': 'six', '7': 'eight', 'three': '3', '9': 'nine'}
for key in d:
if key in d2.itervalues():
print "found"
Your solution is almost right. You have to add not to proof the opposite (not disjoint == have common elements) and use the method values() to get values from the dictionary. In your case you check only keys of two dictionaries.
d1 = {i: i for i in range(5)}
d2 = {i: j for i, j in zip(range(5), range(5,10))}
d3 = {i: j for i, j in zip(range(5,10), range(5))}
print('d1: ', d1)
print('d2: ', d2)
print('Keys of d1 in values of d2: ', not set(d1).isdisjoint(d2.values()))
print('Keys of d1 in keys of d2: ', not set(d1).isdisjoint(d2))
print()
print('d2: ', d2)
print('d3: ', d3)
print('Keys of d2 in values of d3: ', not set(d2).isdisjoint(d3.values()))
print('Keys of d2 in keys of d3: ', not set(d2).isdisjoint(d3))
Output:
# d1: {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}
# d2: {0: 5, 1: 6, 2: 7, 3: 8, 4: 9}
# Keys of d1 in values of d2: False
# Keys of d1 in keys of d2: True
#
# d2: {0: 5, 1: 6, 2: 7, 3: 8, 4: 9}
# d3: {5: 0, 6: 1, 7: 2, 8: 3, 9: 4}
# Keys of d2 in values of d3: True
# Keys of d2 in keys of d3: False

How to "sort" a dictionary by number of occurrences of a key?

I have a dictionary of values that gives the number of occurrences of a value in a list. How can I return a new dictionary that divides the former dictionary into separate dictionaries based on the value?
In other words, I want to sort this dictionary:
>>> a = {'A':2, 'B':3, 'C':4, 'D':2, 'E':3}
to this one.
b = {2: {'A', 'D'}, 3: {'B', 'E'}, 4: {'C'}}
How do I approach the problem?
from collections import defaultdict
a = {'A': 2, 'B': 3, 'C': 4, 'D': 2, 'E': 3}
b = defaultdict(set)
for k, v in a.items():
b[v].add(k)
This is what you'll get:
defaultdict(<class 'set'>, {2: {'D', 'A'}, 3: {'B', 'E'}, 4: {'C'}})
You can convert b to a normal dict afterwards with b = dict(b).
if you are a python beginner like me, you probably wanna try this
a = {'A': 2 , 'B': 3 , 'C' : 4 , 'D' : 2, 'E' : 3}
b = {}
for key in a:
lst = []
new_key = a[key]
if new_key not in b:
lst.append(key)
b[new_key] = lst
else:
b[new_key].append(key)
print(b)
It uses the mutable property of python dictionary to achieve the result you want.

Dictionary comprehension with conditional

So I'm wondering if anyone can help me out with this issue I'm having.
Lets assume I have a dictionary:
d = {1: {2: 3}, 4: 5}
I want to create a dictionary of any contained dictionaries:
wanted_result = {2: 3}
what I am trying is this:
e = {inner_key: d[key][inner_key] for key in d.keys() for inner_key in d[key].keys() if isinstance(d[key], dict)}
However this is causing me to get an error saying that ints don't have keys, which I know, but I thought my conditional would exclude say 4 from my example from being included in the comprehension.
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
s = {k: v for elem in d.values() if type(elem) is dict for k, v in elem.items()}
>> {2: 3, 7: 8}
In this case, I would recommend you a for-loop and the update method:
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
inner_dicts = {}
for val in d.values():
if type(val) is dict:
inner_dicts.update(val)
print inner_dicts
# {2: 3, 7: 8}
My first idea was something like this:
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
generator = (x.items() for x in d.itervalues() if type(x) == dict)
s = dict(sum( generator, list() ))
# s = {2: 3, 7: 8}
But, in order to avoid letting sum() construct a large temporary list of all the items() you may use itertools.chain and iteritems() instead:
# chain "concatenates" iterables
from itertools import chain
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
s = dict(chain( *(x.iteritems() for x in d.itervalues() if type(x) == dict) ))
# s = {2: 3, 7: 8}
You should be aware of edge cases. Especially if identical keys are in the part-dictionaries these will necessarily collapse somehow.
If you also want to support subclasses of dict to be collected from your d.values(), you may indeed want to use isinstance instead of type. See this question for details.
The following list comprehension will return each value that is a dict:
>>> d = {1: {2: 3}, 4: 5}
>>> [d[i] for i in d.keys() if isinstance(d[i],dict)]
[{2: 3}]
d = {1: {2: 3}, 4: 5,'j':{7:8}}
e={y:d[x][y] for x in d if isinstance(d[x],dict) for y in d[x]}
print(e)
{2: 3, 7: 8}
Other way using lambda
(lambda x: {k:v for x in d.values() if type(x) == dict for k,v in x.items()})(d)

Categories