Python: Merge 2 dictionaries and add 0 if key is empty - python

I have 2 dicts as follows:
d1 = {a:2, b:4}
d2 = {a:13, b:3, c:5}
How to merge these two and add 0 if one key is empty?
The result should be
= {a:[2,13], b:[4,3], c:[0,5]}
I tried to use this
d1 = {'a':2, 'b':4}
d2 = {'a':13, 'b':3, 'c':5}
dd = defaultdict(list)
for d in (d1, d2):
for key, value in d.items():
dd[key].append(value)
but I don't know how to add 0, I'm really new to programming.

You can get the list of keys then generate the required dictionary by using dict.get and default value as 0
d1 = {'a':2, 'b':4}
d2 = {'a':13, 'b':3, 'c':5}
keys = set((*d1.keys(), *d2.keys()))
new_dict = {k: [d.get(k, 0) for d in [d1, d2]] for k in keys}
print(new_dict) #{'a': [2, 13], 'b': [4, 3], 'c': [0, 5]}

Use below code.
d1 = {'a':2, 'b':4}
d2 = {'a':13, 'b':3, 'c':5}
keys = set((*d1.keys(), *d2.keys()))
result={}
for k in keys:
result[k]=list((d1.get(k, 0), d2.get(k,0)))
print(result)#{'a': [2, 13], 'b': [4, 3], 'c': [0, 5]}

Related

Append value to a list which in nested dictionary

Basically I need to populate d3 from d2 and d1
d1 = {'Spain':['Madrid,'Barcelona'],'France':['Paris','Nice'],'Germany':['Dortmund','Berlin']}
d2 = {'Madrid':[1,2]'Barcelona':[2],'Paris':[3,4],'Nice':[4],'Dortmund':[5],'Berlin':[6]}
Desired output d3 is as follows:
d3 = {'Spain':{'Madrid':[1,2]},{'Barcelona':[2]},'France':{'Paris':[3,4]},{'Nice':[4]},'Germany':{'Dortmund':{[5]},{'Berlin':[6]}}
I tried following but no luck, I am stuck
l = []
def getKeysByValue(dictOfElements, valueToFind):
listOfKeys = list()
listOfItems = dictOfElements.items()
for item in listOfItems:
if item[1] == valueToFind:
listOfKeys.append(item[0])
return listOfKeys
for i in d2.keys():
for j in d1.values():
if i in j:
name = str(getKeysByValue(d1,j))
l.append({i:name2})
d3[name] = l
print(d3)
You can use a dict comprehension to achieve this.
d1 = {'Spain': ['Madrid','Barcelona'],
'France': ['Paris','Nice'],
'Germany': ['Dortmund','Berlin']}
d2 = {'Madrid': [1,2],
'Barcelona': [2],
'Paris': [3,4],
'Nice': [4],
'Dortmund': [5],
'Berlin':[6]}
d3 = {k: {city: d2[city] for city in v} for k, v in d1.items()}
It is iterating through the keys and values of d1. For every key, the value is a dictionary with each element in the value list as the key, and the d2 value of that key as the value.
You can simply create d3 like this:
d1 = {'Spain':['Madrid','Barcelona'],'France':['Paris','Nice'],'Germany':['Dortmund','Berlin']}
d2 = {'Madrid':[1,2],'Barcelona':[2],'Paris':[3,4],'Nice':[4],'Dortmund':[5],'Berlin':[6]}
d3 = {country:{city:d2[city] for city in cities} for (country,cities) in d1.items()}
print(d3)
Output:
{'Spain': {'Madrid': [1, 2], 'Barcelona': [2]}, 'France': {'Paris': [3, 4], 'Nice': [4]}, 'Germany': {'Dortmund': [5], 'Berlin': [6]}}
I have taken the liberty of correcting your data sources.
d1 = {'Spain':['Madrid','Barcelona'],'France':['Paris','Nice'],'Germany':['Dortmund','Berlin']}
d2 = {'Madrid':[1,2], 'Barcelona':[2],'Paris':[3,4],'Nice':[4],'Dortmund':[5],'Berlin':[6]}
d3 = {}
for k, v in d1.items():
data = {}
for item in v:
if item in d2: # to escape from an KeyError from d2 dictionary
data[item] = d2[item]
d3[k] = data

Merge 2 dictionaries with higher value for each key [duplicate]

This question already has answers here:
keep highest value of duplicate keys in dicts
(6 answers)
Closed 2 years ago.
I have
dict1 = {a: 1, b: 2, c: 3}
dict2 = {b: 3, c: 2}
How do I merge dict1 and dict2 so that the result dict3 will have {a: 1, b: 3, c: 3}
I know we can merge like this dict3 = {**a, **b}, but is there a condition anywhere I have to write to make it work for my problem?
Here you go:
dict1 = {"a": 1, "b": 2, "c": 3}
dict2 = {"b": 3, "c": 2}
result = {}
for k in dict1.keys() | dict2.keys():
result[k] = max(dict1.get(k, float('-inf')), dict2.get(k,float('-inf')))
print(result)
I am using a get with default: dict1.get(k, DEFAULT) and joining the two keysets with the bitwise OR operator |.
Note that the default of float('-inf') means the result for
dict1 = {"a": -1, "b": 2, "c": 3}
dict2 = {"b": -5, "c": 2}```
becomes {'a': -1, 'b': 2, 'c': 3}.
While for the default of 0 you would get
{'b': 2, 'c': 3, 'a': 0}
Both ways could be considered equally valid responses.
You can merge the dict items into one sequence of tuples, sort them, and then use the dict constructor to create a new dict from the sorted sequence so that items of the same keys but with higher values will override those with lower values:
dict(sorted((*dict1.items(), *dict2.items())))
You could simply loop through them and compare the values, and use dict.setdefault(key, 0) to get around unset values.
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'b': 3, 'c': 2}
dict3 = {}
for d in dict1, dict2:
for k, v in d.items():
if v > dict3.setdefault(k, 0):
dict3[k] = v
print(dict3) # -> {'a': 1, 'b': 3, 'c': 3}
defaultdict(int) would also work but I wanted to avoid the import.

Python: summarizing data from list using index from another list

I have two lists:
L1 = ['A','B','A','C','A']
L2 = [1, 4, 6, 1, 3]
I want to create a dictionary which has the following output:
DictOutSum = {'A':10, 'B':4, 'C':1}
DictOutCount = {'A':3, 'B':1, 'C':1}
i.e. Lists L1 and L2 both have same number of elements and the elements in them corresponds one to one. I want to find sum of all numbers in L2 for each unique element in L1 and make a dictionary out of it(DictOutSum). I also want to create another dictionary which stores the counts of number of unique elements of L1(DictOutCount).
I don't even have an idea where to start for this other than to use a for loop.
Pure python implementation:
>>> dict_sum = dict.fromkeys(L1, 0)
>>> dict_count = dict.fromkeys(L1, 0)
>>> for k,n in zip(L1, L2):
... dict_sum[k] += n
... dict_count[k] += 1
...
>>> dict_sum
{'A': 10, 'B': 4, 'C': 1}
>>> dict_count
{'A': 3, 'B': 1, 'C': 1}
Fancy one-liner implementations:
>>> from collections import Counter
>>> Counter(L1) # dict_count
Counter({'A': 3, 'B': 1, 'C': 1})
>>> sum((Counter({k:v}) for k,v in zip(L1, L2)), Counter()) # dict_sum
Counter({'A': 10, 'B': 4, 'C': 1})
You should use the zip builtin function
import collections
DictOutSum = collections.defaultdict(int)
DictOutCount = collections.defaultdict(int)
for l1, l2 in zip(L1, L2):
DictOutSum[l1] += l2
DictOutCount[l1] += 1
>>> L1 = ['A','B','A','C','A']
>>> L2 = [1, 4, 6, 1, 3]
>>>
>>> DictOutCount = {v:0 for v in L1}
>>> DictOutSum = {v:0 for v in L1}
>>> for v1,v2 in zip(L1,L2):
... DictOutCount[v1] += 1
... DictOutSum[v1] += v2
...
>>>
>>> DictOutCount
{'A': 3, 'C': 1, 'B': 1}
>>> DictOutSum
{'A': 10, 'C': 1, 'B': 4}
>>>
The mega elementary way
L1 = ['A','B','A','C','A']
L2 = [1, 4, 6, 1, 3]
# Carries the information
myDict = {}
# Build the dictionary
for x in range(0,len(L1)):
# Initialize the dictionary IF the key doesn't exist
if L1[x] not in myDict:
myDict[L1[x]] = {}
myDict[L1[x]]['sum'] = 0
myDict[L1[x]]['count'] = 0
# Collect the information you need
myDict[L1[x]][x] = L2[x]
myDict[L1[x]]['sum'] += L2[x]
myDict[L1[x]]['count'] += 1
# Build the other two dictionaries
DictOutSum = {}
DictOutCount = {}
# Literally feed the data
for element in myDict:
DictOutSum[element] = myDict[element]['sum']
DictOutCount[element] = myDict[element]['count']
print DictOutSum
# {'A': 10, 'C': 1, 'B': 4}
print DictOutCount
# {'A': 3, 'C': 1, 'B': 1}
Side note: From your username, are you Persian?
DictOutCount, use collections.Counter,
import collections
DictOutCount = collections.Counter(L1)
print(DictOutCount)
Counter({'A': 3, 'C': 1, 'B': 1})
DictOutSum,
DictOutSum = dict()
for k, v in zip(L1, L2):
DictOutSum[k] = DictOutSum.get(k, 0) + v
print(DictOutSum)
# Output
{'A': 10, 'C': 1, 'B': 4}
Previous answer, DictOutSum,
import itertools
import operator
import functools
DictOutSum = dict()
for name, group in itertools.groupby(sorted(itertools.izip(L1, L2)), operator.itemgetter(0)):
DictOutSum[name] = functools.reduce(operator.add, map(operator.itemgetter(1), group))
print(DictOutSum)
{'A': 10, 'C': 1, 'B': 4}
The main steps are:
use itertools.izip to make an iterator that aggregates elements from each of L1 and L2
use itertools.groupby to make an iterator that returns consecutive keys and groups from the iterable (sorting before that)
use functools.reduce for cumulatively addition

Merge python Dictionaries [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have around 1000 of dictionary like this.
x = {'a':1, 'b': 2, 'c':5}
y = {'b':10, 'c': 11}
z = {'e':5, 'b': 2}
I want a merged dictionary like this.
f = {'a':[1,0,0], 'b': [2,10,2], 'c':[5,11,0], 'e':[0,0,5]}
Is there a iterative way to do this.? After creating the final dictionary i want to create a matrix where a , b, c, e will be the column heading with three rows as shown below:
a b c e
1 2 5 0
0 10 11 0
0 2 0 5
keys = ('a', 'b', 'c', 'e')
dicts = (x, y, z)
f = {k: [d.get(k, 0) for d in dicts] for k in keys}
Or as a one-liner:
f = {k: [d.get(k, 0) for d in (x, y, z)] for k in ('a', 'b', 'c', 'e')}
You can get your keys with dict.viewkeys and a reduce function, then use collections.defaultdict to append the corresponding values to keys :
>>> x = {'a':1, 'b': 2, 'c':5}
>>> y = {'b':10, 'c': 11}
>>> z = {'e':5, 'b': 2}
>>> l=[x,y,z]
>>> keys=reduce(lambda i,j: i | j ,[j.viewkeys() for j in l])
>>> from collections import defaultdict
>>> d=defaultdict(list)
>>> for k in keys :
... for i in l:
... d[k].append(i.get(k,0))
...
>>> d
defaultdict(<type 'list'>, {'a': [1, 0, 0], 'c': [5, 11, 0], 'b': [2, 10, 2], 'e': [0, 0, 5]})
Then you can create the proper matrix :
>>> [[i]+j for i,j in d.items()]
[['a', 1, 0, 0], ['c', 5, 11, 0], ['b', 2, 10, 2], ['e', 0, 0, 5]]
Here's how to perform the two tasks:
from collections import defaultdict
dicts = [{'a':1, 'b': 2, 'c':5},
{'b':10, 'c': 11},
{'e':5, 'b': 2}]
# determine what keys exist in the dictionaries and sort them
keys = sorted(reduce(lambda a,b: a|b, (set(d) for d in dicts)))
f = defaultdict(list)
for k in keys:
for d in dicts:
f[k].append(d.get(k, 0))
print 'merged\n f: {}'.format(dict(f))
matrix = [keys] + [[d.get(k, 0) for k in keys] for d in dicts]
print '\nmatrix:'
for row in matrix:
print ' '.join('{:>2}'.format(elem) for elem in row)
Output:
merged
f: {'a': [1, 0, 0], 'c': [5, 11, 0], 'b': [2, 10, 2], 'e': [0, 0, 5]}
matrix:
a b c e
1 2 5 0
0 10 11 0
0 2 0 5

Is there any pythonic way to combine two dicts (making a list for common values)?

For example, I have two dicts.
A = {'a':1, 'b':10, 'c':2}
B = {'b':3, 'c':4, 'd':10}
I want a result like this:
{'a':1, 'b': [10, 3], 'c':[2, 4], 'd':10}
If a key appears in both the dicts, I want to list of both the values.
I'd make all values lists:
{k: filter(None, [A.get(k), B.get(k)]) for k in A.viewkeys() | B}
using dictionary view objects.
Demo:
>>> A = {'a':1, 'b':10, 'c':2}
>>> B = {'b':3, 'c':4, 'd':10}
>>> {k: filter(None, [A.get(k), B.get(k)]) for k in A.viewkeys() | B}
{'a': [1], 'c': [2, 4], 'b': [10, 3], 'd': [10]}
This at least keeps your value types consistent.
To produce your output, you need to use the set intersection and symmetric differences between the two dictionaries:
dict({k: [A[k], B[k]] for k in A.viewkeys() & B},
**{k: A.get(k, B.get(k)) for k in A.viewkeys() ^ B})
Demo:
>>> dict({k: [A[k], B[k]] for k in A.viewkeys() & B},
... **{k: A.get(k, B.get(k)) for k in A.viewkeys() ^ B})
{'a': 1, 'c': [2, 4], 'b': [10, 3], 'd': 10}
In Python 3, dict.keys() is a dictionary view, so you can just replace all .viewkeys() calls with .keys() to get the same functionality there.
I would second the notion of Martijn Pieters that you problably want to have the same type for all the values in your result dict.
To give a second option:
you could also use the defaultdict to achieve your result quite intuitively.
a defaultdict is like a dict, but it has a default constructor that is called if the key doesn't exist yet.
so you would go:
from collections import defaultdict
A = {'a':1, 'b':10, 'c':2}
B = {'b':3, 'c':4, 'd':10}
result = defaultdict(list)
for d in [A, B]:
for k, v in d.items():
result[k].append(v)
then in a later stage you still easily add more values to your result.
you can also switch to
defaultdict(set)
if you don't want duplicate values

Categories