how to merge 2 dictionaries into a new dictionary in python - python

I'm trying to write a function that merges the items in multiple dictionaries under a single dictionary for matching keys.
For example, given
dict1 = {1:3, 2:4}
dict2 = {1:5, 2:6}
the function must return:
dict3 = {1:(3,5),2:(4,6)}
I also want the values to be numerically sorted, i.e. like this:
{1:(3,5)}
instead of this:
{1:(5,3)}
So far, I tried this, but it didn't work as I expected:
def mergeDicts(dict1, dict2):
dict3 = {**dict1, **dict2}
for key, value in dict3.items():
if key in dict1 and key in dict2:
dict3[key] = (value , dict1[key])
return dict3

You may use a defaultdict and a list as type of value, then iterate both dict1 and dict2 and their value in the list pointed by the key
def mergeDicts(dict1, dict2):
dict3 = defaultdict(list)
for key, value in dict1.items():
dict3[key].append(value)
for key, value in dict2.items():
dict3[key].append(value)
return dict(dict3)
Generic method that can accept any amount of dict as parameters
def mergeDicts(*dicts):
dict3 = defaultdict(list)
for d in dicts:
for key, value in d.items():
dict3[key].append(value)
return dict(dict3)
Achieving the same with dict-comprehension
def mergeDicts(dict1, dict2):
return {k: [dict1[k], dict2[k]] for k in dict1}
def mergeDicts(*dicts):
return {k: [d[k] for d in dicts] for k in dicts[0]}

You can do like this:
dict1 = {1:3, 2:4}
dict2 = {1:5, 2:6}
ds = [dict1, dict2]
d = {}
for k in dict1.iterkeys():
d[k] = tuple(d[k] for d in ds)
print(d)

I believe this is closer to what you want than the other answer.
def mergeDicts(dict1, dict2):
dict3 = {}
for key, value in dict1.items():
if key in dict2:
dict3[key] = (value, dict2[key])
return dict3

You could do it lke this:
dict1 = {1:3, 2:4}
dict2 = {1:5, 2:6}
def mergeDicts(dict1, dict2):
dict3 = {}
for key, value in dict1.items():
dict3[key] = (value, dict2[key])
return dict3

Assume keys are going to be same in both dictionary
def mergeDicts(dict1, dict2):
dict3 = {}
for i in dict1.keys():
dict3[i] = dict1[i], dict2[i]
return dict3

Assuming the dicts might have fully/partially different keys:
def mergeDicts(d1:dict, d2:dict):
keys=set(list(d1.keys())+list(d2.keys()))
keys_inter=set(d1.keys()).intersection(d2.keys())
d=dict()
for k in keys:
d[k]=[d1[k], d2[k]] if k in keys_inter else [(d1.get(k, None) or d2.get(k, None))]
return d

The following provides exactly the output that you are seeking.
from collections import defaultdict
from itertools import chain
dict1 = {1:3, 2:4}
dict2 = {1:5, 2:6}
dict3 = defaultdict(list)
for (k,v) in chain(dict1.items(), dict2.items()):
dict3[k].append(v)
for k in dict3.keys():
dict3[k] = tuple(dict3[k])
output
defaultdict(<class 'list'>, {1: (3, 5), 2: (4, 6)})

Related

Update dictionary key(s) by drop starts with value from key in Python

I have a dictionary dict:
dict = {'drop_key1': '10001', 'drop_key2':'10002'}
The key(s) in dict startswith drop_, i would like to update dict by dropping drop_ value from key(s):
dict = {'key1': '10001', 'key2':'10002'}
What is the best approach to do it?
something like
d1 = {'drop_key1': '10001', 'drop_key2':'10002'}
d2 = {k[5:]:v for k,v in d1.items()}
print(d2)
output
{'key1': '10001', 'key2': '10002'}
One approach is, for each key value in the dictionary, you can replace the part of the string with the new string value. For instance:
d = {k.replace('drop_', ''): v for k, v in d.items() if k.strip().startswith('drop_')}
or you can define a function, and get the index of the searched string ("drop_"). If the search string index is 0, then remove it. For instance:
def change_key(key, search):
start_idx = key.find(search)
if start_idx == 0:
key = key.replace(search, "")
return key
d = {change_key(k, search="drop_"): v for k, v in d.items()}
Result:
{'key1': '10001', 'key2': '10002'}
Note that if you use a method, then you can guarantee to remove the search string if it is at the beginning of the string. For instance:
d = {' drop_key1': '10001', 'drop_key2': '10002'}
d = {change_key(k, search="drop_"): v for k, v in d.items()}
Result:
{' drop_key1': '10001', 'key2': '10002'}

Nested Dictionary Python:Update logic failing

My dictionary :
d={'a':'a1,a2,a3,a4','b':'b1,b2,b3,b4',c:'c1,c2,c3,c4'}
and so on d,e,f,....
d2={'a1':'a11,a12,a13,a14,a15','a2':'a21,a22,a23,a24,a25'}
and so on for a3,a4,a5,b1,b2....
Expected output
dict1={'a':{'a1':'a11,a12,a13,a14,a15','a2':'a21,a22,a23,a24,a25'}}
and so on for rest
My Output
dict1={'a':{'a1':'a11,a12,a13,a14,a15'},'a2':'a21,a22,a23,a24,a25'}
and so on then again
'b':{'b1':'b11,b12,b13,b14,b15'},'b2':'b21,b22,b23,b24,b25'}
My Code:
dict1={}
for i in d:
q=d[i].split(",")
for j in q:
dict1[i] = {}
if j in d2:
dict1[i][j] = d2[j]
dict1.update(dict1[i])
Any help would be very useful
You can try nested dictionary comprehension with list comprehension
d={'a':'a1,a2,a3,a4','b':'b1,b2,b3,b4','c':'c1,c2,c3,c4'}
d2={'a1':'a11,a12,a13,a14,a15','a2':'a21,a22,a23,a24,a25', 'b1':'b11,b12,b13,b14,b15','b2':'b21,b22,b23,b24,b25'}
dict1 = {k: {i: d2[i] for i in v.split(",") if i in d2} for k, v in d.items()})
print(dict1)
Output in this case
{'a': {'a1': 'a11,a12,a13,a14,a15', 'a2': 'a21,a22,a23,a24,a25'}, 'b': {'b1': 'b11,b12,b13,b14,b15', 'b2': 'b21,b22,b23,b24,b25'}, 'c': {}}
So if there will be values in d2 about the the c's they will be in the dict1 results as well.
Maybe you can try with:
dict1={}
for i in d:
q=d[i].split(",")
for j in q:
if not dict1.get(i, None):
dict1[i] = {}
if j in d2:
dict1[i][j] = d2[j]

Python Join 2 dictionaries into 3rd, 2D dictionary where key from dictionary 2 is list value in dictionary 1

I couldn't find this particular python dictionary question anywhere.
I have two dictionaries:
dict1 = {'key1':['val1','val2','val3']}
dict2 = {'val1':['a','b','c']}
I want a 3rd, 2D dictionary with:
dict3 = {'key1': {'val1':['a','b','c']} }
So, joining 2 dictionaries where the key of the second dictionary is a list value of the first dictionary.
I was trying some nested looping along the lines of:
for key1, val1 in dict1.items():
for key2, in val2 in dict2.items():
# do something here
I am not sure if that is the best way to do this.
This is best done by iterating over dict1 and looking for matching values in dict2:
result = {}
for key, value_list in dict1.items():
result[key] = subdict = {}
for value in value_list:
try:
subdict[value] = dict2[value]
except KeyError:
pass
Result:
{'key1': {'val1': ['a', 'b', 'c']}}
You can use a dictionary comprehension and then check if the final result contains only one dictionary. If the latter is true, then a dictionary of dictionaries will be the final result; else, a listing of dictionaries will be stored for the key:
dict1 = {'key1':['val1','val2','val3']}
dict2 = {'val1':['a','b','c']}
new_dict = {a:[{i:dict2[i]} for i in b if i in dict2] for a, b in dict1.items()}
last_result = {a:b if len(b) > 1 else b[0] for a, b in new_dict.items()}
Output:
{'key1': {'val1': ['a', 'b', 'c']}}
dict1 = {
'key1':['val1','val2','val3']
}
dict2 = {
'val1':['a','b','c']
}
dict3 = {
key : { val_key : dict2[val_key]
for val_key in val_list if (val_key in dict2.keys())
} for key, val_list in dict1.items()
}
You can try this solution .
dict1 = {'key1':['val1','val2','val3']}
dict2 = {'val1':['a','b','c']}
join_dict={}
for i,j in dict1.items():
for sub_l,sub_value in dict2.items():
if sub_l in j:
join_dict[i]={sub_l:sub_value}
print(join_dict)
output:
{'key1': {'val1': ['a', 'b', 'c']}}

In python, combine the values of 2 dictionaries

I'm new to Python, and I have two questions regarding dictionary in python.
I have dict1 (where the values is already a list), then I have dict2with the same keys as dict1, I want to add the new value to the list of values in dict1. How can I write it? Can you show it with an example?
dict1 = {'uid': ['u1'], 'sid': ['s1'], 'os': ['os1']}
dict2 = {'uid': ['u2'], 'sid': ['s2'], 'os': ['os2']}
Expected output:
dict1 = {'uid': ['u1', 'u2'], 'sid': ['s1', 's2'], 'os': ['os1', 'os2']}
I will be process a lot of lines in a text file, with each line creating a new dictionary. Here is the idea of my code:
count = 0
for line in f:
if count == 0:
dict1 = parse_qs(line)
count = count+1
else:
dict2 = parse_qs(line)
#combine dict1 with dict 2, and assign the new dict to dict1
Is there a better way that uses less memory or runs faster (still using dictionary)?
Thank you in advance for your help!
Since you're apparently not allowed to rewrite you parser, you can do:
for k in dict1:
dict1[k].extend(dict2.get(k, []))
You can drop the .get and use direct subscription if the keys from both dicts are always matching.
for k in dict1:
dict1[k].extend(dict2[k])
Otherwise, you can create one defaultdict(list) and let your parser append values to that.
You can do like this,
for key in dict1.keys():
if dict2.has_key(key):
dict1[key].extend(dict2[key])
if you are using python3 you can use key in dict2 instead of dict2.has_key(key).
Result
{'os': ['os1', 'os2'], 'sid': ['s1', 's2'], 'uid': ['u1', 'u2']}
If you don't want the two dictionaries anymore then you can do this:
def merge_dict(dict1, dict2):
for k in dict1:
try:
dict1[k].extend(dict2[k])
except KeyError:
pass
return dict1
Else if you want to preserve them both for future use, try this
def merge_dict(dict1, dict2):
new_dict = {}
keys = dict1.keys() + dict2.keys()
for k in keys:
try:
new_dict[k] = dict1[k]
except KeyError:
new_dict[k] = dict2[k]
continue
try:
new_dict[k]+= dict2[k]
except KeyError:
pass
return dict1
this may be helpful to you.
from itertools import chain
from collections import defaultdict
# ------ for dict1 -------#
u1 = [1,2,3]
s1 = ['a','b','c']
x1 = [10,100,1000]
# ------ for dict2 -------#
u2 = [4,5,6]
s2 = ['d','e','f']
x2 = ['aa','bb','cc']
dict1 = {1:u1,2:s1,3:x1}
dict2 = {1:u2,2:s2,3:x2}
dict3 = defaultdict(list)
for a, b in chain(dict1.items(), dict2.items()):
dict3[a].append(b)
#for a, b in dict3.items():
# print(a, b)
print dict3

remove the keys which has blank values

how to remove keys in a dict which do not have any value. I have a dict as :
d = {'CB': '', 'CA': [-7.5269999504089355, -2.2330000400543213, 6.748000144958496], 'C': [-8.081000328063965, -3.619999885559082, 6.406000137329102], 'N': [-6.626999855041504, -2.318000078201294, 7.9029998779296875], 'H':''}
I want to remove keys which values are blank. I need output as :
d = {'CA': [-7.5269999504089355, -2.2330000400543213, 6.748000144958496], 'C': [-8.081000328063965, -3.619999885559082, 6.406000137329102], 'N': [-6.626999855041504, -2.318000078201294, 7.9029998779296875]}
how to do this?
Use a dict-comprehension:
>>> {k:v for k, v in d.items() if v != ''}
{'N': [-6.626999855041504, -2.318000078201294, 7.9029998779296875], 'CA': [-7.5269999504089355, -2.2330000400543213, 6.748000144958496], 'C': [-8.081000328063965, -3.619999885559082, 6.406000137329102]}
If by empty you meant any falsy value then use just if v.
If you want to modify the original dict itself(this will affect all the references to the dict object):
for k, v in d.items():
if not v: del d[k]
>> {key:value for key, value in d.items() if value}
If you really need to do this in one-line:
for k in [k for k,v in d.iteritems() if not v]: del d[k]
This is ugly. It makes a list of all of the keys in d that have a "blank" value and then iterates over this list removing the keys from d (to avoid the unsafe removal of items from dictionary during iteration).
I'd suggest that three lines would be more readable:
blanks = [k for k,v in d.iteritems() if not v]
for k in blanks:
del d[k]
If making a fresh dict is acceptable, use a dict comprehension:
d2 = {k:v for k,v in d.iteritems() if not v}

Categories