Python. How to merge two dictionaries with the same keys? - python

I have two dicts:
a = {'a': 1, 'b': 2, 'c': 3}
b = {'a': 2, 'd': 4, 'c': 5}
and i want to get:
{'a': 2, 'b': 2, 'c': 5}
i used {**a, **b} but it return:
{'a': 2, 'b': 2, 'c': 5, 'd': 4}
Help me please exclude keys from b which not in a with the simplest and fastest way.
i have python 3.7

You have to filter the elements of the second dict first in order to not add any new elements. I got two possible solutions:
a = {'a': 1, 'b': 2, 'c': 3}
b = {'a': 2, 'd': 4, 'c': 5}
for k,v in b.items():
if (k in a.keys()):
a[k] = v
print(a)
a = {'a': 1, 'b': 2, 'c': 3}
b = {'a': 2, 'd': 4, 'c': 5}
a.update([(k,v) for k, v in b.items() if k in a.keys()])
print(a)
Output for both:
{'a': 2, 'b': 2, 'c': 5}

I think a comprehension is easy enough:
{ i : (b[i] if i in b else a[i]) for i in a }

Related

How to reverse order of values but not keys in a python dictionnary?

What is the best way to reverse order of values but not keys in a python dictionnary ?
dictionnary = {'a': 3, 'b': 2, 'c': 1}
inversed_values = dictionnary.reverseValues()
print(inversed_values)
This should print out {'a': 1, 'b': 2, 'c': 3}
You can convert values to list then reverse them then create dict like below:
>>> dct = {'a': 3, 'b': 2, 'c': 1}
>>> dict(zip(dct.keys(),list(dct.values())[::-1]))
{'a': 1, 'b': 2, 'c': 3}

list of dictionary compare first value of first dict with first value of next dict

I have a list of dictionaries, for example:
l = [{"a":1, "b":2, "c":3}, {"a":1, "b":2, "c":4}, {"a":1, "b":7, "c":4}, {"a":2, "b":7, "c":4}]
I need to create a nested dictionary if value of "a" are equal.
I have tried:
l2 = [l[i] for i in range(len(l)-1) if l[i].get('a') == l[i+1].get('a')]
d = {"element"+ str(index): x for index, x in enumerate(l2, start=1)}
But in the output, I'm getting it skips one element:
{'element1': {'a': 1, 'b': 2, 'c': 3}, 'element2': {'a': 1, 'b': 2, 'c': 4}}
Expected output:
{'element1': {'a': 1, 'b': 2, 'c': 3}, 'element2': {'a': 1, 'b': 2, 'c': 4}, 'element3': {"a":1, "b":7, "c":4}}
Could someone please help me, what am I doing wrong?
Try this:
out = {f'element{i + 1}': j for i, j in enumerate(l) if any(j['a'] == k['a'] for k in l[:i] + l[i+1:])}
Output:
{'element1': {'a': 1, 'b': 2, 'c': 3}, 'element2': {'a': 1, 'b': 2, 'c': 4}, 'element3': {'a': 1, 'b': 7, 'c': 4}}

How to change specific values in dictionary regardless of the keys in python?

How can I change the values in a dictionary in python regardless of the keys? If we take the following dictionary for our example:
d = {'a': 1, 'b': 2, 'c': 0, 'd': 2, 'e': 1}
Now I want to manipulate the dictionary in the way that all the values 2 will be changed into 3 so the output would be:
d = {'a': 1, 'b': 3, 'c': 0, 'd': 3, 'e': 1}
I am sure the problem is very basic, but I somehow haven't managed to find the answer online.
Thank you in advance.
In [338]: d = {'a': 1, 'b': 2, 'c': 0, 'd': 2, 'e': 1}
In [339]: for k,v in d.items():
...: if v == 2:
...: d[k] = 3
...:
In [340]: d
Out[340]: {'a': 1, 'b': 3, 'c': 0, 'd': 3, 'e': 1}

Explode a dict - Get all combinations of the values in a dictionary

I want to get all combinations of the values in a dictionary as multiple dictionaries (each containing every key of the original but only one value of the original values). Say I want to parametrize a function call with:
kwargs = {'a': [1, 2, 3], 'b': [1, 2, 3]}
How do I get a list of all the combinations like this:
combinations = [{'a': 1, 'b': 1}, {'a': 1, 'b': 2}, {'a': 1, 'b': 3},
{'a': 2, 'b': 1}, {'a': 2, 'b': 2}, {'a': 2, 'b': 3},
{'a': 3, 'b': 1}, {'a': 3, 'b': 2}, {'a': 3, 'b': 3}]
There can be an arbitary amount of keys in the original kwargs and each value is garantueed to be an iterable but the number of values is not fixed.
If possible: the final combinations should be a generator (not a list).
You can flatten the kwargs to something like this
>>> kwargs = {'a': [1, 2, 3], 'b': [1, 2, 3]}
>>> flat = [[(k, v) for v in vs] for k, vs in kwargs.items()]
>>> flat
[[('b', 1), ('b', 2), ('b', 3)], [('a', 1), ('a', 2), ('a', 3)]]
Then, you can use itertools.product like this
>>> from itertools import product
>>> [dict(items) for items in product(*flat)]
[{'a': 1, 'b': 1},
{'a': 2, 'b': 1},
{'a': 3, 'b': 1},
{'a': 1, 'b': 2},
{'a': 2, 'b': 2},
{'a': 3, 'b': 2},
{'a': 1, 'b': 3},
{'a': 2, 'b': 3},
{'a': 3, 'b': 3}]
itertools.product actually returns an iterator. So you can get the values on demand and build your dictionaries. Or you can use map, which also returns an iterator.
>>> for item in map(dict, product(*flat)):
... print(item)
...
...
{'b': 1, 'a': 1}
{'b': 1, 'a': 2}
{'b': 1, 'a': 3}
{'b': 2, 'a': 1}
{'b': 2, 'a': 2}
{'b': 2, 'a': 3}
{'b': 3, 'a': 1}
{'b': 3, 'a': 2}
{'b': 3, 'a': 3}
Just another way, building the value tuples first and then combining with keys afterwards (pretty much the opposite of #thefourtheye's way :-).
>>> combinations = (dict(zip(kwargs, vs)) for vs in product(*kwargs.values()))
>>> for c in combinations:
print(c)
{'a': 1, 'b': 1}
{'a': 1, 'b': 2}
{'a': 1, 'b': 3}
{'a': 2, 'b': 1}
{'a': 2, 'b': 2}
{'a': 2, 'b': 3}
{'a': 3, 'b': 1}
{'a': 3, 'b': 2}
{'a': 3, 'b': 3}

How to join 2 lists of dicts in python?

I have 2 lists like this:
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
and I want to obtain a list l3, which is a join of l1 and l2 where values of 'a' and 'b' are equal in both l1 and l2
i.e.
l3 = [{'a': 1, 'b: 2, 'c': 3, 'd': 4, 'e': 101}, {'a': 5, 'b: 6, 'c': 7, 'd': 8, 'e': 100}]
How can I do this?
You should accumulate the results in a dictionary. You should use the values of 'a' and 'b' to form a key of this dictionary
Here, I have used a defaultdict to accumulate the entries
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
from collections import defaultdict
D = defaultdict(dict)
for lst in l1, l2:
for item in lst:
key = item['a'], item['b']
D[key].update(item)
l3 = D.values()
print l3
output:
[{'a': 1, 'c': 3, 'b': 2, 'e': 101, 'd': 4}, {'a': 5, 'c': 7, 'b': 6, 'e': 100, 'd': 8}]
Simple list operations would do the thing for you as well:
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
l3 = []
for i in range(len(l1)):
for j in range(len(l2)):
if l1[i]['a'] == l2[j]['a'] and l1[i]['b'] == l2[j]['b']:
l3.append(dict(l1[i]))
l3[i].update(l2[j])
My approach is to sort the the combined list by the key, which is keys a + b. After that, for each group of dictionaries with similar key, combine them:
from itertools import groupby
def ab_key(dic):
return dic['a'], dic['b']
def combine_lists_of_dicts(list_of_dic1, list_of_dic2, keyfunc):
for key, dic_of_same_key in groupby(sorted(list_of_dic1 + list_of_dic2, key=keyfunc), keyfunc):
combined_dic = {}
for dic in dic_of_same_key:
combined_dic.update(dic)
yield combined_dic
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
for dic in combine_lists_of_dicts(l1, l2, ab_key):
print dic
Discussion
The function ab_key returns a tuple of value for key a and b, used for sorting a groupping
The groupby function groups all the dictionaries with similar keys together
This solution is less efficient than that of John La Rooy, but should work fine for small lists
One can achieve a nice and quick solution using pandas.
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
import pandas as pd
pd.DataFrame(l1).merge(pd.DataFrame(l2), on=['a','b']).to_dict('records')

Categories

Resources