In python, combine the values of 2 dictionaries - python

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

Related

how to merge 2 dictionaries into a new dictionary in 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)})

Remove elements from dict in for loop

How can I delete all elements in a dictionary after a modified one?
If the second one is changed, then we delete everything that is behind it or, if the first one is changed, then we delete everything after it and so on.
d = {'first': 'one', 'second': 'two', 'third': 'three'}
k = 'second'
for key in d:
if k in key:
d[key] = 'new value'
# delete third
Instead of deleting elements, just create a new dictionary.
Since dictionaries are not ordered, you should sort the items in some way.
d = {'first': 'one', 'second': 'two', 'third': 'three'}
k = 'second'
new_d = {}
for key, value in sorted(d.items()):
if key == k:
new_d[key] = 'new value'
break
new_d[key] = value
You can use the following code. it makes the dict items into a list and creates a new dict from the remaining items:
d = {'first': 'one', 'second': 'two', 'third': 'three'}
k = 'second'
d[k] = 'NewValue'
d = dict(list(d.items())[:list(d.keys()).index(k)+1])
print(d)
Out:
{'first': 'one', 'second': 'NewValue'}
Out of curiosity I timed it against #Daniel's answer those are my timeit code and result:
import timeit, functools
def test_1(d,k):
d = dict(list(d.items())[:list(d.keys()).index(k)+1])
d[k] = 'new vlaue'
return d
def test_2(d, k):
new_d = {}
for key, value in sorted(d.items()):
if key == k:
new_d[key] = 'new value'
break
new_d[key] = value
return new_d
if __name__ == '__main__':
keys = [x for x in range(100000)]
values = [x for x in range(100000)]
d = dict(zip(keys, values))
k = 9999
a = timeit.timeit(functools.partial(test_1, d, k), number = 1000)
b = timeit.timeit(functools.partial(test_2, d, k), number = 1000)
print(a, b)
Output:
5.107241655999815 6.745305094000059
If you change the sorted(...) into list(...) in Daniels answer it is the other way around:
5.046288972999946 4.211456709999993
It is a constant offset, probably due to creating the list out of the dict twice instead of once. So #Daniels answer is both faster and less memory expensive
you can delete rest of dict by keys. like below:
d = {'first': 'one', 'second': 'two', 'third': 'three'}
k = 'first' #for modify
keys = ['second', 'third'] #rest of dict to delete
list(map(d.pop, keys))
it will return {'first':'modified_value'}
You should not be using normal dictionary if you're trying to keep them in an order, at least if you're below py3.7 of course.
Please use if you're below 3.7.
We are creating a new dictionary in the below code and removing the old one, you can even put this inside a function and use it.
from collections import OrderedDict
d =OrderedDict([('first','one'), ('second', 'two'), ('third', 'three')])
k = 'second'
output_dict = OrderedDict()
for key,value in d.items():
if k in key:
output_dict[key] = value
break
else:
output_dict[key] = value
del d
print(output_dict)

Group list of dict results using python based on first key from each item

I am trying to find the output of this list of dict using Python. Because foo and data are unique keys, the output should merge them.
input = [{'foo': 'foo-main-123'}, {'foo': 'foo-main-345'}, {'data': 'data-main-111'}]
output = {'foo', ['foo-main-123', 'foo-main-345'], 'data': ['data-main-111']}
you can use defaultdict(list), then iterate each k,v pair in each dict in input.
try this:
from collections import defaultdict
input = [{'foo': 'foo-main-123'}, {'foo': 'foo-main-345'}, {'data': 'data-main-111'}]
output = defaultdict(list)
for d in input:
for k,v in d.items():
output[k].append(v)
output=dict(output)
print(output)
Output:
{'foo': ['foo-main-123', 'foo-main-345'], 'data': ['data-main-111']}

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']}}

How to list all the keys with the same value in a dictionary? [duplicate]

I have question about Dictionaries in Python.
here it is:
I have a dict like dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
Now i want to get all Key-Elements by the same value and save it in a new dict.
The new Dict should be look like:
new_dict = { 'b':('cdf'), 'a':('abc','gh'), 'g':('fh','hfz')}
If you are fine with lists instead of tuples in the new dictionary, you can use
from collections import defaultdict
some_dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
new_dict = defaultdict(list)
for k, v in some_dict.iteritems():
new_dict[v].append(k)
If you want to avoid the use of defaultdict, you could also do
new_dict = {}
for k, v in some_dict.iteritems():
new_dict.setdefault(v, []).append(k)
Here's a naive implementation. Someone with better Python skills can probably make it more concise and awesome.
dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
new_dict = {}
for pair in dict.items():
if pair[1] not in new_dict.keys():
new_dict[pair[1]] = []
new_dict[pair[1]].append(pair[0])
print new_dict
This produces
{'a': ['abc', 'gh'], 'b': ['cdf'], 'g': ['fh', 'hfz']}
If you do specifically want tuples as the values in your new dictionary, you can still use defaultdict, and use tuple concatenation. This solution works in Python 3.4+:
from collections import defaultdict
source = {'abc': 'a', 'cdf': 'b', 'gh': 'a', 'fh': 'g', 'hfz': 'g'}
target = defaultdict(tuple)
for key in source:
target[source[key]] += (key, )
print(target)
Which will produce
defaultdict(<class 'tuple'>, {'a': ('abc', 'gh'), 'g': ('fh', 'hfz'), 'b': ('cdf',)})
This will probably be slower than generating a dictionary by list insertion, and will create more objects to be collected. So, you can build your dictionary out of lists, and then map it into tuples:
target2 = defaultdict(list)
for key in source:
target2[source[key]].append(key)
for key in target2:
target2[key] = tuple(target2[key])
print(target2)
Which will give the same result as above.
It can be done this way too, without using any extra functions .
some_dict = { 'abc':'a', 'cdf':'b', 'gh':'a', 'fh':'g', 'hfz':'g' }
new_dict = { }
for keys in some_dict:
new_dict[some_dict[keys]] = [ ]
for keys in some_dict:
new_dict[some_dict[keys]].append(keys)
print(new_dict)

Categories