I've been stuck on this question for quite sometime and just can't figure it out. I just want to be able to understand what I'm missing and why it's needed.
What I need to do is make a function which adds each given key/value pair to the dictionary. The argument key_value_pairs will be a list of tuples in the form (key, value).
def add_to_dict(d, key_value_pairs):
newinputs = [] #creates new list
for key, value in key_value_pairs:
d[key] = value #updates element of key with value
if key in key_value_pairs:
newinputs.append((d[key], value)) #adds d[key and value to list
return newinputs
I can't figure out how to update the "value" variable when d and key_value_pairs have different keys.
The first three of these scenarios work but the rest fail
>>> d = {}
>>> add_to_dict(d, [])
[]
>>> d
{}
>>> d = {}
>>> add_to_dict(d, [('a', 2])
[]
>>> d
{'a': 2}
>>> d = {'b': 4}
>>> add_to_dict(d, [('a', 2)])
[]
>>> d
{'a':2, 'b':4}
>>> d = {'a': 0}
>>> add_to_dict(d, [('a', 2)])
[('a', 0)]
>>> d
{'a':2}
>>> d = {'a', 0, 'b': 1}
>>> add_to_dict(d, [('a', 2), ('b': 4)])
[('a', 2), ('b': 1)]
>>> d
{'a': 2, 'b': 4}
>>> d = {'a': 0}
>>> add_to_dict(d, [('a', 1), ('a': 2)])
[('a', 0), ('a':1)]
>>> d
{'a': 2}
Thanks
Edited.
Python has this feature built-in:
>>> d = {'b': 4}
>>> d.update({'a': 2})
>>> d
{'a': 2, 'b': 4}
Or given you're not allowed to use dict.update:
>>> d = dict(d.items() + {'a': 2}.items()) # doesn't work in python 3
With python 3.9 you can use an |= update operator:
>>> d = {'b': 4}
>>> d |= {'a': 2}
>>> d
{'a': 2, 'b': 4}
Here's a more elegant solution, compared to Eric's 2nd snippet
>>> a = {'a' : 1, 'b' : 2}
>>> b = {'a' : 2, 'c' : 3}
>>> c = dict(a, **b)
>>> a
{'a': 1, 'b': 2}
>>> b
{'a': 2, 'c': 3}
>>> c
{'a': 2, 'b': 2, 'c': 3}
It works both in Python 2 and 3
And of course, the update method
>>> a
{'a': 1, 'b': 2}
>>> b
{'a': 2, 'c': 3}
>>> a.update(b)
>>> a
{'a': 2, 'b': 2, 'c': 3}
However, be careful with the latter, as might cause you issues in case of misuse like here
>>> a = {'a' : 1, 'b' : 2}
>>> b = {'a' : 2, 'c' : 3}
>>> c = a
>>> c.update(b)
>>> a
{'a': 2, 'b': 2, 'c': 3}
>>> b
{'a': 2, 'c': 3}
>>> c
{'a': 2, 'b': 2, 'c': 3}
The new version of Python3.9 introduces two new operators for dictionaries: union (|) and in-place union (|=). You can use | to merge two dictionaries, while |= will update a dictionary in place. Let's consider 2 dictionaries d1 and d2
d1 = {"name": "Arun", "height": 170}
d2 = {"age": 21, "height": 170}
d3 = d1 | d2 # d3 is the union of d1 and d2
print(d3)
Output:
{'name': 'Arun', 'height': 170, 'age': 21}
Update d1 with d2
d1 |= d2
print(d1)
Output:
{'name': 'Arun', 'height': 170, 'age': 21}
You can update d1 with a new key weight as
d1 |= {"weight": 80}
print(d1)
Output:
{'name': 'Arun', 'height': 170, 'age': 21, 'weight': 80}
So if I understand you correctly you want to return a list of of tuples with (key, old_value) for the keys that were replaced.
You have to save the old value before you replace it:
def add_to_dict(d, key_value_pairs):
newinputs = [] #creates new list
for key, value in key_value_pairs:
if key in d:
newinputs.append((key, d[key]))
d[key] = value #updates element of key with value
return newinputs
Each key in a python dict corresponds to exactly one value. The cases where d and key_value_pairs have different keys are not the same elements.
Is newinputs supposed to contain the key/value pairs that were previously not present in d? If so:
def add_to_dict(d, key_value_pairs):
newinputs = []
for key, value in key_value_pairs:
if key not in d:
newinputs.append((key, value))
d[key] = value
return newinputs
Is newinputs supposed to contain the key/value pairs where the key was present in d and then changed? If so:
def add_to_dict(d, key_value_pairs):
newinputs = []
for key, value in key_value_pairs:
if key in d:
newinputs.append((key, value))
d[key] = value
return newinputs
If I understand you correctly, you only want to add the keys that do not exist in the dictionary. Here is the code:
def add_to_dict(d, key_value_pairs):
newinputs = [];
for key, value in key_value_pairs:
if key not in d.keys():
d[key] = value
newinputs.append((key, value));
return newinputs
For each key in new key,value pairs list you have to check if the key is new to the dictionary and add it only then.
Hope it helps ;)
Related
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
I have the following dictionary:
my_dict = {"A":0, "B":[1,2], "C":3}
I am trying to split this into a list of 2 dictionaries that encompass each possible value. For example:
#Desired result
[{"A":0, "B":1, "C":3}, {"A":0, "B":2, "C":3}]
I am able to get a list of each needed dictionary, in hopes I can then loop through the list and merge dictionaries using update(). This will overwrite the key "B"and only create a single dict.
Here is what I have done:
dict_list = []
my_dict = {"A":0, "B":[1,2], "C":3}
for k, v in my_dict.items():
if type(v) == list:
for i in v:
dict1 = {k:i}
dict_list.append(dict1)
if type(v) != list:
dict2 = {k:v}
dict_list.append(dict2)
new_dict = {}
for d in dict_list:
new_dict.update(d)
print(new_dict)
Output:
{'A':0, 'B':2, 'C':3}
This is overwriting the key 'B' and creating only one dictionary based on the last value.
It's pretty easy if your dict can have only one list.
>>> my_dict = {"A":0, "B":[1,2], "C":3}
>>> k, lst = next((k, v) for k, v in my_dict.items() if isinstance(v, list))
>>> [{**my_dict, k:x} for x in lst]
[{'A': 0, 'B': 1, 'C': 3}, {'A': 0, 'B': 2, 'C': 3}]
It's a bit trickier if your dict can have multiple lists.
>>> from itertools import product
>>>
>>> my_dict = {"A":0, "B":[1,2], "C":[3, 4]}
>>> lists_kv = ([(k, x) for x in v] for k, v in my_dict.items() if isinstance(v, list))
>>> [{**my_dict, **dict(x)} for x in product(*lists_kv)]
[{'A': 0, 'B': 1, 'C': 3},
{'A': 0, 'B': 1, 'C': 4},
{'A': 0, 'B': 2, 'C': 3},
{'A': 0, 'B': 2, 'C': 4}]
dict1 = {a: 5, b: 7}
dict2 = {a: 3, c: 1}
result {a:8, b:7, c:1}
How can I get the result?
this is a one-liner that would do just that:
dict1 = {'a': 5, 'b': 7}
dict2 = {'a': 3, 'c': 1}
result = {key: dict1.get(key, 0) + dict2.get(key, 0)
for key in set(dict1) | set(dict2)}
# {'c': 1, 'b': 7, 'a': 8}
note that set(dict1) | set(dict2) is the set of the keys of both your dictionaries. and dict1.get(key, 0) returns dict1[key] if the key exists, 0 otherwise.
this works on a more recent python version:
{k: dict1.get(k, 0) + dict2.get(k, 0) for k in dict1.keys() | dict2.keys()}
You can use collections.Counter which implements addition + that way:
>>> from collections import Counter
>>> dict1 = Counter({'a': 5, 'b': 7})
>>> dict2 = Counter({'a': 3, 'c': 1})
>>> dict1 + dict2
Counter({'a': 8, 'b': 7, 'c': 1})
if you really want the result as dict you can cast it back afterwards:
>>> dict(dict1 + dict2)
{'a': 8, 'b': 7, 'c': 1}
Here is a nice function for you:
def merge_dictionaries(dict1, dict2):
merged_dictionary = {}
for key in dict1:
if key in dict2:
new_value = dict1[key] + dict2[key]
else:
new_value = dict1[key]
merged_dictionary[key] = new_value
for key in dict2:
if key not in merged_dictionary:
merged_dictionary[key] = dict2[key]
return merged_dictionary
by writing:
dict1 = {'a': 5, 'b': 7}
dict2 = {'a': 3, 'c': 1}
result = merge_dictionaries(dict1, dict2)
result will be:
{'a': 8, 'b': 7, 'c': 1}
A quick dictionary comprehension that should work on any classes which accept the + operator. Performance might not be optimal.
{
**dict1,
**{ k:(dict1[k]+v if k in dict1 else v)
for k,v in dict2.items() }
}
Here is another approach but it is quite lengthy!
d1 = {'a': 5, 'b': 7}
d2 = {'a': 3, 'c': 1}
d={}
for i,j in d1.items():
for k,l in d2.items():
if i==k:
c={i:j+l}
d.update(c)
for i,j in d1.items():
if i not in d:
d.update({i:j})
for m,n in d2.items():
if m not in d:
d.update({m:n})
Think it's much simpler.
a={'a':3, 'b':5}
b= {'a':4, 'b':7}
{i:a[i]+b[i] for i in a.keys()}
Output: {'a': 7, 'b': 12}
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}
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.