I have function which returns something like this
{a:{b:{c:4}}}
and when i again call that function in loop it will return
{a:{b:{d:5}}}
and again it will return
{a:{b:{e:6}}}
So i want my final output to be {a:{b:{c:4, d:5, e:6}}}
I tried
final_output.update(func)
But this will update as final_output as {a:{b:{e:6}}}
def create_dict(self, make_dict, key, value):
final_dict = make_dict
keys = key.split('.')
latest = keys.pop()
for key in keys:
final_dict = final_dict.setdefault(key, {})
final_dict.setdefault(latest, value)
self.create_dict(status_dict, '{}.{}.{}'.format(name, ton_set.id, ton_id),
status)
Here is my function func = create_dict.
Will a defaultdict help me in this situation?
def update_only_new(original_dict, to_add):
for key in to_add.iterkeys():
if key not in original_dict:
original_dict[key] = to_add[key]
else:
update_only_new(original_dict[key], to_add[key])
> dct={}
> d1 = {'a': {'b': {'c': 4}}}
> d2 = {'a': {'b': {'d': 5}}}
> d3 = {'a': {'b': {'e': 6}}}
> update_only_new(dct,d1)
> print dct
{'a': {'b': {'c': 4}}}
> update_only_new(dct,d2)
> print dct
{'a': {'b': {'c': 4, 'd': 5}}}
> update_only_new(dct,d3)
> print dct
{'a': {'b': {'c': 4, 'e': 6,'d': 5}}}
You could write a function like this one:
def update_dict(my_dict, value, key):
my_dict[key] = value
return my_dict
my_dict = {}
my_dict = update_dict(my_dict, 4, 'key')
print(my_dict)
d1={'a': {'b': {'c': 4}}}
d2={'a': {'b': {'d': 5}}}
d3={'a': {'b': {'e': 6}}}
d3['a']['b'].update(dict(d1['a']['b'].items() + d2['a']['b'].items()))
print d3 {'a': {'b': {'c': 4, 'e': 6, 'd': 5}}}
Related
I have a loop:
all_rec = {}
for i in range(0, 2):
rec = buildings[best_buildings[i]]['recommendations']
The value of 'rec' after first iteration:
rec = {'a': {'b': 2, 'c': 1}, 'd': {'e': 5}}
The value of 'rec' after second iteration:
rec = {'d': {'e': 4}}
The data type of 'recommendations' is a dictionary. How can I add all the 'rec' dictionaries resulting from this loop into one dictionary 'all_rec'?
I want 'all_rec' to look like this:
all_rec = {'a': {'b': 2, 'c': 1}, 'd': {'e': 5}, 'd': {'e': 4}}
Keeping both 'd': {'e': 5} and 'd': {'e': 4} in the new dictionary. How can I do that in Python 2.7?
If you need to keep all such values, it suggests that the values in the lower dictionaries should be lists, at least for the summary list:
all_rec = {}
for i in range(0, 2):
rec = buildings[best_buildings[i]]['recommendations']
for dk, dc in rec.items():
if dk not in all_rec:
all_rec[dk] = {k:[v] for k,v in dc.items()}
else:
for k,v in dc.items():
if k in all_rec[dk]:
all_rec[dk][k].append(v)
else:
all_rec[dk][k] = [v]
print(all_rec)
{'a': {'b': [2], 'c': [1]}, 'd': {'e': [5,4]}}
This is Python 3.7; I don't know how you'd need to adjust to use 2.7 but I kept it as basic as possible.
I do not have your data but this is the rough idea:
If you want to sum the recommentations:
from collections import defaultdict
all_rec = defaultdict(lambda: defaultdict(int))
for i in range(0, 2):
rec[buildings[best_buildings[i]]] += buildings[best_buildings[i]]['recommendations']
If you want to append the recommendations:
from collections import defaultdict
all_rec = defaultdict(lambda: defaultdict(list))
for i in range(0, 2):
rec[buildings[best_buildings[i]]].append(buildings[best_buildings[i]]['recommendations'])
---
DEMO
>>> from collections import defaultdict
>>>
>>> demo = defaultdict(lambda: defaultdict(int))
>>> demo['a']['b'] += 1
>>> demo
defaultdict(<function <lambda> at 0x7f931a2d2700>, {'a': defaultdict(<class 'int'>, {'b': 1})})
>>> demo['a']['b'] += 1
>>> demo
defaultdict(<function <lambda> at 0x7f931a2d2700>, {'a': defaultdict(<class 'int'>, {'b': 2})})
>>>
>>> demo = defaultdict(lambda: defaultdict(list))
>>> demo['a']['b'].append(1)
>>> demo
defaultdict(<function <lambda> at 0x7f931a2d2b80>, {'a': defaultdict(<class 'list'>, {'b': [1]})})
>>> demo['a']['b'].append(1)
>>> demo
defaultdict(<function <lambda> at 0x7f931a2d2b80>, {'a': defaultdict(<class 'list'>, {'b': [1, 1]})})
>>>
I'm just too confused, and can't come up with proper way to do this:
I have this directed graph:
and have two dictionaries, which show outgoing and incoming scores
graph_to = {'a':{'b':2,'c':3},'b':{'a':1,'d':4}}
graph_from = {'a':{'b':1},'b':{'a':2},'c':{'a':3},'d':{'b':4}}
For example, in graph_to, node a goes to node b with score 2 and to node c with score 3; and in graph_from node a receives score 1 from node b.
I want to create undirected graph such that scores between two nodes are summed up. It should become this dictionary:
graph = {
'a':{'b':3,'c':3},
'b':{'a':3,'d':4},
'c':{'a':3},
'd':{'b':4}
}
You could try to make a collections.defaultdict() of collections.Counter() objects, and sum the edge counts as you iterate both graph dicts:
from collections import defaultdict
from collections import Counter
from pprint import pprint
graph_to = {'a':{'b':2,'c':3},'b':{'a':1,'d':4}}
graph_from = {'a':{'b':1},'b':{'a':2},'c':{'a':3},'d':{'b':4}}
undirected_graph = defaultdict(Counter)
def sum_edges(graph, result):
for node, edges in graph.items():
for edge in edges:
result[node][edge] += edges[edge]
sum_edges(graph_to, undirected_graph)
sum_edges(graph_from, undirected_graph)
pprint(undirected_graph)
Which gives:
defaultdict(<class 'collections.Counter'>,
{'a': Counter({'b': 3, 'c': 3}),
'b': Counter({'d': 4, 'a': 3}),
'c': Counter({'a': 3}),
'd': Counter({'b': 4})})
Note: Counter and defaultdict are subclasses of dict, so you can treat them the same as normal dictionaries.
If you really want normal dictionaries in the final undirected graph, you can use either of these dict comprehensions:
dict((k, dict(v)) for k, v in undirected_graph.items())
# {'a': {'b': 3, 'c': 3}, 'b': {'a': 3, 'd': 4}, 'c': {'a': 3}, 'd': {'b': 4}}
{k: dict(v) for k, v in undirected_graph.items()}
# {'a': {'b': 3, 'c': 3}, 'b': {'a': 3, 'd': 4}, 'c': {'a': 3}, 'd': {'b': 4}}
Additionally, you can also use dict.update() here to refactor sum_edges():
def sum_edges(graph, result):
for node, edges in graph.items():
result[node].update(edges)
I hope we appreciate taking things in own hand, here's with simple logic
out_dict = {}
for key in graph_to :
for sub_key in graph_to[key]:
if key in graph_from and sub_key in graph_from[key]:
out_dict[key] = {sub_key: graph_to[key][sub_key] + graph_from[key][sub_key]}
else:
out_dict[key].update({sub_key: graph_to[key][sub_key]})
graph_from.update(out_dict)
print(graph_from)
Output:
{'a': {'b': 3, 'c': 3}, 'b': {'a': 3, 'd': 4}, 'c': {'a': 3}, 'd': {'b': 4}}
mylist = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 5, 'f': 6}]
i want it as
myDict ={'a': 1, 'b': 2,'c': 3, 'd': 4,'e': 5, 'f': 6}
You can make use of ChainMap.
from collections import ChainMap
myDict = dict(ChainMap(*mylist ))
This will take each dictionary and iterate through its key value pairs in for (k,v) in elem.items() part and assign them to a new dictionary.
mylist = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 5, 'f': 6}]
new_dict = {k:v for elem in mylist for (k,v) in elem.items()}
print new_dict
This will replace the duplicated keys.
I would create a new dictionary, iterate over the dictionaries in mylist, then iterate over the key/value pairs in that dictionary. From there, you can add each key/value pair to myDict.
mylist = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 5, 'f': 6}]
myDict = {}
for Dict in mylist:
for key in Dict:
myDict[key] = Dict[key]
print(myDict)
Assuming that there are two python list with the same structure like this:
var1 = [{'a':1,'b':2},{'c':2,'d':5,'h':4},{'c':2,'d':5,'e':4}]
var2 = [{'a':3,'b':2},{'c':1,'d':5,'h':4},{'c':5,'d':5,'e':4}]
In my case, i need to combine both of those list, so i'll get this value :
result = [{'a':4,'b':4},{'c':3,'d':10,'h':8},{'c':7,'d':10,'e':8}]
How can i do that?
zip-based one-liner comprehension:
result = [{k: d1[k]+d2[k] for k in d1} for d1, d2 in zip(var1, var2)]
This assumes that two dicts at the same index always have identical key sets.
Use list comprehensions to put the code in one line,
result = [{key : d1.get(key, 0)+d2.get(key, 0)
for key in set(d1.keys()) | set(d2.keys())} # union two sets
for d1, d2 in zip(var1, var2)]
print(result)
[{'a': 4, 'b': 4}, {'h': 8, 'c': 3, 'd': 10}, {'c': 7, 'e': 8, 'd': 10}]
This code takes into consideration the case that two dictionaries may not have the same keys.
var1 = [{'a':1,'b':2},{'c':2,'d':5,'h':4},{'c':2,'d':5,'e':4}]
var2 = [{'a':3,'b':2},{'c':1,'d':5,'h':4},{'c':5,'d':5,'e':4}]
res = []
for i in range(len(var1)):
dic = {}
dic1, dic2 = var1[i], var2[i]
for key, val in dic1.items(): // dic1.iteritems() in python 2.
dic[key] = dic1[key] + dic2[key]
res.append(dic)
>>>print(res)
[{'a': 4, 'b': 4}, {'c': 3, 'd': 10, 'h': 8}, {'c': 7, 'd': 10, 'e': 8}]
var1 = [{'a': 1, 'b': 2}, {'c': 2, 'd': 5, 'h': 4}, {'c': 2, 'd': 5, 'e': 4}]
var2 = [{'a': 3, 'b': 2}, {'c': 1, 'd': 5, 'h': 4}, {'c': 5, 'd': 5, 'e': 4}]
ret = []
for i, ele in enumerate(var1):
d = {}
for k, v in ele.items():
value = v
value += var2[i][k]
d[k] = value
ret.append(d)
print(ret)
For the sake of completeness, another zip-based one-liner that will work even if the dicts are uneven in the both lists:
result = [{k: d1.get(k, 0) + d2.get(k, 0) for k in set(d1) | set(d2)} for d1, d2 in zip(var1, var2)]
Would something like this help?
ar1 = [{'a':1,'b':2},{'c':2,'d':5,'h':4},{'c':2,'d':5,'e':4}]
var2 = [{'a':3,'b':2},{'c':1,'d':5,'h':4},{'c':5,'d':5,'e':4}]
combined_var = zip(var1, var2)
new_d = {}
list_new_ds = []
for i, j in combined_var:
new_d = {}
for key in i and j:
new_d[key] = i[key] + j[key]
list_new_ds.append(new_d)
list_new_ds = [{'a': 4, 'b': 4}, {'h': 8, 'c': 3, 'd': 10}, {'c': 7, 'e': 8, 'd': 10}]
To explain, the zip function merges the lists as a list of tuples. I then unpack the tuples and iterate through the keys in each dictionary and add the values for the same keys together using a new dictionary to store them. I then append the value to a list, and then re-initialise the temporary dictionary to empty before looking at the next tuple in the zipped list.
The order is different due to dictionary behaviour I believe.
I am a novice, so would appreciate any critiques of my answer!
If I have:
dicts = [{'a': 4,'b': 7,'c': 9},
{'a': 2,'b': 1,'c': 10},
{'a': 11,'b': 3,'c': 2}]
How can I get the maximum keys only, like this:
{'a': 11,'c': 10,'b': 7}
Use collection.Counter() objects instead, or convert your dictionaries:
from collections import Counter
result = Counter()
for d in dicts:
result |= Counter(d)
or even:
from collections import Counter
from operator import or_
result = reduce(or_, map(Counter, dicts), Counter())
Counter objects support finding the maximum per key natively through the | operation; & gives you the minimum.
Demo:
>>> result = Counter()
>>> for d in dicts:
... result |= Counter(d)
...
>>> result
Counter({'a': 11, 'c': 10, 'b': 7})
or using the reduce() version:
>>> reduce(or_, map(Counter, dicts), Counter())
Counter({'a': 11, 'c': 10, 'b': 7})
>>> dicts = [{'a': 4,'b': 7,'c': 9},
... {'a': 2,'b': 1,'c': 10},
... {'a': 11,'b': 3,'c': 2}]
>>> {letter: max(d[letter] for d in dicts) for letter in dicts[0]}
{'a': 11, 'c': 10, 'b': 7}
dicts = [{'a': 4,'b': 7,'c': 9},
{'a': 2,'b': 1,'c': 10},
{'a': 11,'b': 3,'c': 2}]
def get_max(dicts):
res = {}
for d in dicts:
for k in d:
res[k] = max(res.get(k, float('-inf')), d[k])
return res
>>> get_max(dicts)
{'a': 11, 'c': 10, 'b': 7}
Something like this should work:
dicts = [{'a': 4,'b': 7,'c': 9},
{'a': 2,'b': 1,'c': 10},
{'a': 11,'b': 3,'c': 2}]
max_keys= {}
for d in dicts:
for k, v in d.items():
max_keys.setdefault(k, []).append(v)
for k in max_keys:
max_keys[k] = max(max_keys[k])