dictionary merging for certain keys - python

So I want to try and merge only certain keys from one dictionary to another so doing
a = {'a':2, 'b':3, 'c':5}
b = {'d':2, 'e':4}
a.update(b)
>>> a
{'a': 2, 'c': 5, 'b': 3, 'e': 4, 'd': 2} # returns a merge of all keys
However say you only wanted the key and value pair 'd':2 and not all of the elements within the dictionary how would this be possible so you get:
{'a': 2, 'c': 5, 'b': 3, 'd': 2}

If you know you want to update a with b['d'], use this:
a['d'] = b['d']

I don't know if I got what you're asking. Anyway, if you want to update just some keys on a dictionary with keys from another, you can do:
a['d'] = b['d']
or, if you want to update multiple keys:
for to_update in keys_to_update: # keys_to_update is a list
a[to_update] = b[to_update]

You may use following snippet:
a = {'a':2, 'b':3, 'c':5}
b = {'d':2, 'e':4}
desiredKeys = ('d',)
for key, val in b.items():
if key in desiredKeys:
a[key] = b[key]
print( a )
Sample above will output:
{'d': 2, 'b': 3, 'c': 5, 'a': 2}

Related

How to sum dict elements inside dicts

In Python I have a list of dictionary containing dictionaries.
list = [{a: {b:1, c:2}}, {d: {b:3, c:4}}, {a: {b:2, c:3}}]
I want one final list with dictionary that contain dictionary that will contain the sum of all dictionary with the same dictionary as the key. i.e. the result will be:
result = [{a: {b:3, c:5}}, {d: {b:3, c:4}}]
N.B: every dictionary in the list will contain same number of key, value pairs.
Code:
lst = [{'a': {'b':1, 'c':2}}, {'d': {'b':3, 'c':4}}, {'a': {'b':2, 'c':3}}]
p={}
for l in lst:
for key , val in l.items():
if key in p and val != p[key]:
p.update({key:{k: p[key].get(k, 0) + val.get(k, 0) for k in set(p[key])}})
else:
p.update(l)
Output:
{'a': {'c': 5, 'b': 3}, 'd': {'b': 3, 'c': 4}}
I don't know if it is the best way to do this, but here it goes:
First I've made a loop for to get all of the primary and secondary keys:
# list containing the data
lista = [{'a': {'b':1, 'c':2}}, {'d': {'b':3, 'c':4}}, {'a': {'b':2, 'c':3}}]
# empty list with keys
primary_keys = []
secondary_keys = []
# for each dict in the list it appends the primary key and the secondary key
for dic in lista:
for key in dic.keys():
primary_keys.append(key)
for key2 in dic[key].keys():
secondary_keys.append(key2)
# prints all the keys
print('Primary keys:',primary_keys)
print('Secondary keys:',secondary_keys)
Results:
Primary keys: ['a', 'd', 'a']
Secondary keys: ['b', 'c', 'b', 'c', 'b', 'c']
Then I've made a final dict with all the combinations:
# creates the final dict from the list
dict_final = dict.fromkeys(primary_keys)
# for all primary keys creates a secondary key
for pkey in dict_final.keys():
dict_final[pkey] = dict.fromkeys(secondary_keys)
# for all secondary keys puts a zero
for skey in dict_final[pkey].keys():
dict_final[pkey][skey] = 0
# prints the dict
print(dict_final)
Results:
{'a': {'b': 0, 'c': 0}, 'd': {'b': 0, 'c': 0}}
And later I've made a loop through each dictionary item and added to the corresponding keys in the final dict
# for each primary and secondary keys in the dic list sums into the final dict
for dic in lista:
for pkey in dict_final.keys():
for skey in dict_final[pkey].keys():
try:
dict_final[pkey][skey] += dic[pkey][skey]
except:
pass
# prints the final dict
print(dict_final)
Results:
{'a': {'b': 3, 'c': 5}, 'd': {'b': 3, 'c': 4}}
By using defaultdict, we can simplify the logic a bit:
# Using default dict
from collections import defaultdict
original_list = [{'a': {'b':1, 'c':2}}, {'d': {'b':3, 'c':4}}, {'a': {'b':2, 'c':3}}]
out = defaultdict(lambda: defaultdict(int))
for outter_dict in original_list:
for outter_key, inner_dict in outter_dict.items():
for inner_key, inner_value in inner_dict.items():
out[outter_key][inner_key] += inner_value
print(out)
out_list = [{key: dict(value) for key, value in out.items()}]
print(out_li)
Output:
defaultdict(<function <lambda> at 0x103c18a60>, {'a': defaultdict(<class 'int'>, {'b': 3, 'c': 5}), 'd': defaultdict(<class 'int'>, {'b': 3, 'c': 4})})
[{'a': {'b': 3, 'c': 5}, 'd': {'b': 3, 'c': 4}}]
Notes
out is a nested defaultdict whose values are yet defaultdict whose values are integers
After the 3 nested loops, we converted the defaultdict out to a list of dictionaries to conform the output requirement

Is there any way to change the keys (not Values) in the dictionary in Python?

I want to change just Keys (not Values) in a Dictionary in Python. Is there any way to do that?
You can pop the value of the old key and reassign:
d = {'A': 1, 'B': 2, 'C': 3}
d['b'] = d.pop('B')
print(d)
# {'A': 1, 'C': 3, 'b': 2}
Note that this won't maintain the order of the keys (python 3.6+). The renamed key will be instead at the end.
maintaining order
If order is important you need to create a new dictionary
d = {'A': 1, 'B': 2, 'C': 3}
rename = {'B': 'b', 'A': 'a'}
d = {rename.get(k, k): v for k,v in d.items()}
print(d)
# {'a': 1, 'b': 2, 'C': 3}
in place modification while maintaining order
If you want to modify the dictionary in place (i.e. not creating a new object), you need to pop and reinsert all keys in order:
d = {'A': 1, 'B': 2, 'C': 3}
rename = {'B': 'b', 'A': 'a'}
keys = list(d)
for k in keys:
d[rename.get(k, k)] = d.pop(k)
print(d)
{'a': 1, 'b': 2, 'C': 3}

Merge Two Dictionaries that Share Same Key:Value

I know this can be done with lists, but I'm just trying to figure out how to do this with dictionaries.
Basically, it'll go like this:
dict1 = {'a': 10, 'b': 12, 'c': 9}
dict2 = {'a': 10, 'b': 3, 'c': 9}
def intersect(dict1, dict2):
combinDict = dict()
....
print(combinDict)
{'a': 10, 'c':9}
So I only want the keys with the same value added into a new dictionary.
Any help?
You want the intersection of the items:
dict1 = {'a': 10, 'b': 12, 'c': 9}
dict2 = {'a': 10, 'b': 3, 'c': 9}
print dict(dict1.viewitems() & dict2.items())
{'a': 10, 'c': 9}
For python 3 you just want to use items:
dict(dict1.items() & dict2.items())
dict1.items() & dict2.items() returns a set of key/value pairings that are common to both dicts:
In [4]: dict1.viewitems() & dict2.items()
Out[4]: {('a', 10), ('c', 9)}
Then we simply call the dict constructor on that.
Another way to do this would be to use a dict comprehension:
In [1]: dict1 = {'a': 10, 'b': 12, 'c': 9}
In [2]: dict2 = {'a': 10, 'b': 3, 'c': 9}
In [3]: {key: dict1[key] for key in dict1 if dict1[key] == dict2.get(key)}
Out[3]: {'a': 10, 'c': 9}
This should be teeny weeny bit faster, though that wouldn't matter for regular dictionaries.

How to access indexes of a list of dictionaries?

Suppose I am give a list of dictionaries, where
dict1 = dict(a = 2, b = 5, c = 7)
dict2 = dict(c = 5, d = 5, e = 1)
dict3 = dict(e = 2, f = 4, g = 10)
list_of_dictionaries = [dict1, dict2, dict3]
How would I be able to, find the value of the highest index (aka the latest dictionary)?
So if I were to write a method to delete an item from the list of dictionaries, let's say I want to delete c from the dictionary.
How would I be able to delete the c from the second dictionary instead of the first?
The key is reversing through the list with reverse indexing (a_list[::-1]).
From there once you find any dictionary that matches the requirements alter it and quit the function or loop - hence the early returns.
This code:
def get_last(bucket,key):
for d in bucket[::-1]:
if key in d.keys():
return d[key]
return None
def set_last(bucket,key,val):
for d in bucket[::-1]:
if key in d.keys():
d[key] = val
return
def pop_last(bucket,key):
out = None
for d in bucket[::-1]:
if key in d.keys():
return d.pop(key)
dict1 = {'a': 2, 'b': 5, 'c': 7}
dict2 = {'c': 5, 'd': 5, 'e': 1}
dict3 = {'e': 2, 'f': 4, 'g': 10}
list_of_dictionaries = [dict1, dict2, dict3]
print get_last(list_of_dictionaries ,'c')
set_last(list_of_dictionaries ,'c',7)
print list_of_dictionaries
popped = pop_last(list_of_dictionaries ,'c')
print popped
print list_of_dictionaries
Gives:
5
[{'a': 2, 'c': 7, 'b': 5}, {'c': 7, 'e': 1, 'd': 5}, {'e': 2, 'g': 10, 'f': 4}]
7
[{'a': 2, 'c': 7, 'b': 5}, {'e': 1, 'd': 5}, {'e': 2, 'g': 10, 'f': 4}]
I am not exactly sure what you mean but I wan to show you a couple of things that might help:
First here is how your dictionaries should look like:
dict1 = {"a" :2, "b" : 5, "c" :7}
dict2 = {"c" :5, "d" :5, "e" :1}
dict3 = {"e" :2, "f" :4, "g" :10}
Then you asked this: "How would I be able to delete the c from the second dictionary instead of the first?"
You can do delete it this way:
del dict2["c"]

Python - Find non mutual items in two dicts

Lets say I have two dictionaries:
a = {'a': 1, 'b': 2, 'c': 3}
b = {'b': 2, 'c': 3, 'd': 4, 'e': 5}
What's the most pythonic way to find the non mutual items between the two of them such that for a and b I would get:
{'a': 1, 'd': 4, 'e': 5}
I had thought:
{key: b[key] for key in b if not a.get(key)}
but that only goes one way (b items not in a) and
a_only = {key: a[key] for key in a if not b.get(key)}.items()
b_only = {key: b[key] for key in b if not a.get(key)}.items()
dict(a_only + b_only)
seams very messy. Any other solutions?
>>> dict(set(a.iteritems()) ^ set(b.iteritems()))
{'a': 1, 'e': 5, 'd': 4}
Try with the symetric difference of set() :
out = {}
for key in set(a.keys()) ^ set(b.keys()):
out[key] = a.get(key, b.get(key))
diff = {key: a[key] for key in a if key not in b}
diff.update((key,b[key]) for key in b if key not in a)
just a bit cheaper version of what you have.
>>> a = {'a': 1, 'b': 2, 'c': 3}
>>> b = {'b': 2, 'c': 3, 'd': 4, 'e': 5}
>>> keys = set(a.keys()).symmetric_difference(set(b.keys()))
>>> result = {}
>>> for k in keys: result[k] = a.get(k, b.get(k))
...
>>> result
{'a': 1, 'e': 5, 'd': 4}
Whether this is less messy than your version is debatable, but at least it doesn't re-implement symmetric_difference.

Categories

Resources