Get max keys of a list of dictionaries - python

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])

Related

Merge dicts from list with getting set of values for equal keys

Do I have any opportunity to rewrite the code below with dict enhancement? (if I name it right, mean {k: v for k, v in ...})
list_of_dicts = [{'a': 1}, {'b': 2}, {'b': 20, 'c': 3}, {'a': 10, 'b': 2}]
for k, v in [p for d in list_of_dicts for p in d.items()]:
d[k] = d.setdefault(k, set()) | {v}
sure why not :). but it is nested at bit 😉
import itertools
list_of_dicts = [{'a': 1}, {'b': 2}, {'b': 20, 'c': 3}, {'a': 10, 'b': 2}]
o = {k: {d[k] for d in list_of_dicts if k in d} for k in itertools.chain.from_iterable(list_of_dicts)}
print(o)

Merge dictionary with recurrence

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

Group all keys with the same value in a dictionary of sets

I am trying to transform a dictionary of sets as the values with duplication to a dictionary with the unique sets as the value and at the same time join the keys together.
dic = {'a': {1, 2, 3}, 'b': {1, 2}, 'c': {1, 3, 2}, 'd': {1, 2, 3}}
Should be changed to
{'a-c-d': {1, 2, 3}, 'b': {1, 2}}
My try is as below, but I think there has to be a better way.
def transform_dictionary(dic: dict) -> dict:
dic = {k: frozenset(v) for k, v in dic.items()}
key_list = list(dic.keys())
value_list = list(dic.values())
dict_transformed = {}
for v_uinque in set(value_list):
sub_key_list = []
for i, v in enumerate(value_list):
if v == v_uinque:
sub_key_list.append(str(key_list[i]))
dict_transformed['-'.join(sub_key_list)] = set(v_uinque)
return dict_transformed
print(transform_dictionary(dic))
You can "invert" the input dictionary into a dictionary mapping frozensets into a set of keys.
import collections
dic = {'a': {1, 2, 3}, 'b': {1, 2}, 'c': {1, 3, 2}, 'd': {1, 2, 3}}
keys_per_set = collections.defaultdict(list)
for key, value in dic.items():
keys_per_set[frozenset(value)].append(key)
Then invert that dictionary mapping back into the desired form:
{'-'.join(keys): value for (value, keys) in keys_per_set.items()}
Output:
{'a-c-d': frozenset({1, 2, 3}), 'b': frozenset({1, 2})}
This will turn the values into a frozenset, but you could "thaw" them with a set(value) in the last list comprehension.
from itertools import groupby
dic_output = {'-'.join(v):g for g,v in groupby(sorted(dic_input,
key=dic_input.get),
key=lambda x: dic_input[x])}
Output
{'b': {1, 2}, 'a-c-d': {1, 2, 3}}

Given key value pairs, sort output alphabetically and increment values

dict1 = {'a': 10, 'b': 8, 'c':5}
dict2 = {'d': 6, 'c': 4, 'a':20}
Given two dictionaries, I'd like an output of.
output = {'a':30, 'b':8, 'c':9, 'd':6}
This is what I've so far, not quite sure what I'd do next.
I'm looking for a solution that is efficient in time/space complexity.
def merge_dict(dict1, dict2):
merged_dictionaries = {**dict1, **dict2}
return merged_dictionaries
dict1 = {'a': 10, 'b': 8, 'c':5}
dict2 = {'d': 6, 'c': 4, 'a':20}
merge_dictionaries = merge_dict (dict1, dict2)
sorted_dictionary = sorted(merge_dictionaries)
If the values are numeric, you can use counters:
from collections import Counter
def merge_dicts(*dicts):
return dict(sum(map(Counter, dicts), Counter()))
dict1 = merge_dicts(dict1, dict2)
dict1
# {'a': 30, 'b': 8, 'c': 9, 'd': 6}
This might be a bit excessive for only two dictionaries, so another option is:
for k, v in dict2.items():
dict1[k] = dict1.setdefault(k, 0) + v
dict1
# {'a': 30, 'b': 8, 'c': 9, 'd': 6}
Which updates dict1 in-place.
Finally, if you really need the result sorted (python3.7+), use
result = {k : dict1[k] for k in sorted(dict1)}
You can use a dict comprehension that iterates over a sorted union of the keys of the two dicts, and outputs values that are sums of the respective values of two dicts by the given keys, defaulting to 0:
{k: dict1.get(k, 0) + dict2.get(k, 0) for k in sorted(dict1.keys() | dict2.keys())}
This returns:
{'a': 30, 'b': 8, 'c': 9, 'd': 6}
result = dict(Counter(dict1) + Counter(dict2))
result = {k: result[k] for k in sorted(result)}
First merge the dicts together by turning them into Counters and convert the result it back into a dict, then sort the dict by keys.
You can Try Collections for add two dictionary..
from collections import Counter
def merged_dic():
dict1 = {'a': 10, 'b': 8, 'c':5}
dict2 = {'d': 6, 'c': 4, 'a':20}
a = Counter(dict1)
b = Counter(dict2)
c = a+b
print(dict(c))
merged_dic()
Output:- {'a': 30, 'b': 8, 'c': 9, 'd': 6}

How to convert list of dictionaries to dictionaries

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)

Categories