Maximum value from dictionary using python - python

s={'a': [11, 22, 33], 'b': [44, 77, 99], 'c': [99, 200, 100]}
Output should be the maximum value from each dictionary like a=33, b=99, c=200.

A simple comprehension:
>>> {k: max(v) for k, v in s.items()}
{'a': 33, 'b': 99, 'c': 200}

Related

Extract dictionary values from nested keys, leaving main key, then turn into list

a = {
1: {'abc': 50, 'def': 33, 'xyz': 40},
2: {'abc': 30, 'def': 22, 'xyz': 45},
3: {'abc': 15, 'def': 11, 'xyz': 50}
}
I would like to iterate through this nested dictionary, remove the sub keys (or extract the subkey values), but keep the main keys. the second step would be to turn the dictionary into a list of lists:
b = [
[1, 50, 33, 40],
[2, 30, 22, 45],
[3, 15, 11, 50]
]
I looked through the myriad of posts here talking about extracting keys and values but cannot find a close enough example to fit to what I need (still new at this): So far, I have this:
for key in a.keys():
if type(a[key]) == dict:
a[key] = a[key].popitem()[1]
which gives this - the value of the third sub key in each key: It's a start, but not complete or what I want
{1: 40, 2: 45, 3: 50}
Use a list comprehension over a.items(), use dict.values() to get the values, and then you can use unpacking (*) to get the desired lists.
>>> [[k, *v.values()] for k,v in a.items()]
[[1, 50, 33, 40], [2, 30, 22, 45], [3, 15, 11, 50]]
This solution may be not the most elegant solution, but it does what you exactly want:
a = {
1: {'abc': 50, 'def': 33, 'xyz': 40},
2: {'abc': 30, 'def': 22, 'xyz': 45},
3: {'abc': 15, 'def': 11, 'xyz': 50}
}
b = []
for key1, dict2 in a.items():
c = [key1]
c.extend(dict2.values())
b.append(c)
print(b)

How to insert values into a nested dictionary from existing dictionary values

I have a dictionary which is like a json format. Like below:-
dito1 ={'result2':[{'math':20,'science':22,'english':31},{'math':26,'science':27,'english':33},
{'math':15,'science':55,'english':44}],'pet2':0,
'result':[{'rt':66,'io':49,'op':10},{'rt':24,'io':25,'op':5}],'pet':20}
Now I want to create a new dictionary using the above values, the new dictionary has to be seen like below:-
{'type': 'etc', 'scores': [{'math': 20, 'science': 22, 'english': 31}, {'math': 26, 'science': 27, 'english': 33}, {'math': 15, 'science': 55, 'english': 44}], 'math total': 61,'scores2':[{'math': 66, 'science': 49, 'english': 10}, {'math': 24, 'science': 25, 'english': 5}],'math total':90}
In the first dictionary there are two keys result2, result that have scores information that are lists. By using this information they must be converted as above and the math total in the second dictionary is total marks of the math's in each list. I have tried to get the desired output but I am not able to divide them into two based on the keys they belong to. The code I have tried is as follows:-
dito1 ={'result2':[{'math':20,'science':22,'english':31},{'math':26,'science':27,'english':33},
{'math':15,'science':55,'english':44}],'pet2':0,
'result':[{'rt':66,'io':49,'op':10},{'rt':24,'io':25,'op':5}],'pet':20}
reslt=[]
math_total=[]
for key,value in dito1.items():
if key == 'result' or key == 'result2':
for i in value:
for k,v in i.items():
if k == 'math':
t=v
if k == 'rt':
t=v
if k == 'science':
r=v
if k == 'io':
r=v
if k=='op':
e=v
if k=='english':
e=v
rest ={'math':t,'science':r,'english':e}
math_total.append(t)
reslt.append(rest)
final_dict={'type':'etc','math total':reslt,'scores':sum(math_total)}
print(final_dict)
The output I got is:-
{'type': 'etc', 'scores': [{'math': 20, 'science': 22, 'english': 31}, {'math': 26, 'science': 27, 'english': 33}, {'math': 15, 'science': 55, 'english': 44}, {'math': 66, 'science': 49, 'english': 10}, {'math': 24, 'science': 25, 'english': 5}], 'math total': 151}
Excepted output:-
{'type': 'etc', 'scores': [{'math': 20, 'science': 22, 'english': 31}, {'math': 26, 'science': 27, 'english': 33}, {'math': 15, 'science': 55, 'english': 44}], 'math total': 61,'scores2':[{'math': 66, 'science': 49, 'english': 10}, {'math': 24, 'science': 25, 'english': 5}],'math total2':90}
As an aside, I'd suggest re-thinking the structure/naming scheme of this final_dict; using keys like 'scores' and 'scores2' indicates you may want a list structure instead of a dict structure.
dito1 = {'result2': [{'math': 20, 'science': 22, 'english': 31}, {'math': 26, 'science': 27, 'english': 33}, {'math': 15, 'science': 55, 'english': 44}], 'pet2': 0, 'result': [{'rt': 66, 'io': 49, 'op': 10}, {'rt': 24, 'io': 25, 'op': 5}], 'pet': 20}
translate = {'rt':'math','io':'science','op':'english'}
final_dict = {'type':'etc'}
for key,list_of_dict in dito1.items():
if key in ['result', 'result2']:
score_key = key.replace('result','scores')
final_dict[score_key] = []
math_total_key = key.replace('result','math_total')
final_dict[math_total_key] = 0
for d in list_of_dict:
# translate to the intended score names as needed
for k in ['rt','io','op']:
if k in d:
d[translate[k]] = d.pop(k)
# append the scores to the appropriate nested dict
final_dict[score_key].append(dict(d))
# and increment the math_total for that set of scores
final_dict[math_total_key] += d['math']
print(final_dict)
results in
for key,value in final_dict.items():
print(f'{key}: {value}')
# Output:
type: etc
scores2: [{'math': 20, 'science': 22, 'english': 31}, {'math': 26, 'science': 27, 'english': 33}, {'math': 15, 'science': 55, 'english': 44}]
math_total2: 61
scores: [{'math': 66, 'science': 49, 'english': 10}, {'math': 24, 'science': 25, 'english': 5}]
math_total: 90

How to compare all possibilities of combining a set of lists of numbers, against a requested list of numbers in Python?

I have this list of lists, that have dictionaries in them:
[
[{'A': [35, 64, 72]}, {'B': [42, 55, 23]}, {'C': [17, 23, 55]}],
[{'A': [35, 64, 72]}, {'B': [42, 55, 23]}, {'C': [17, 23, 55]}],
[{'D': [72]}, {'E': [42]}]
]
And I have another list, the requested list, that looks like this:
[35, 64, 72, 42, 17, 23, 55]
Want I want to achieve is to able to iterate through the available combinations of numbers and see if there are combinations of letters that would match the requested list.
So in this case I would want the output to be
['A', 'C', 'E']
Because if I combine those together I would get a list with same numbers as the requested list.
I really hope I'm explaining this correctly, and I'm sorry if this is something simple already asked. I couldn't find anything about it, but maybe I'm describing my problem in a wrong way.
Any would be much appreciated! I'm stuck..
The OP has added requirements in the comments below this question. It is sufficiently altered, although related, that I have decided to leave this answer in place (to answer the question as shown) and add a separate answer relating to that case.
The problem breaks down into two parts.
Getting your input data into a more convenient format:
data_in = [
[{'A': [35, 64, 72]}, {'B': [42, 55, 23]}, {'C': [17, 23, 55]}],
[{'A': [35, 64, 72]}, {'B': [42, 55, 23]}, {'C': [17, 23, 55]}],
[{'D': [72]}, {'E': [42]}]
]
target_list = [35, 64, 72, 42, 17, 23, 55]
data = {}
for sublist in data_in:
for dct in sublist:
data.update({k: set(v) for k, v in dct.items()})
target = set(target_list)
print(data)
# {'A': {64, 72, 35}, 'B': {42, 23, 55}, 'C': {17, 55, 23}, 'D': {72}, 'E': {42}}
print(target)
# {64, 35, 72, 42, 17, 55, 23}
Having done that, solving the interesting problem. This can be done with a recursive approach:
def find_combos(target, items):
for i, (k, v) in enumerate(items):
if not (v - target):
remaining = target - v
if remaining:
for lst in find_combos(remaining, items[i + 1 :]):
yield [k] + lst
else:
yield [k]
for combo in find_combos(target, list(data.items())):
print(combo)
Prints:
['A', 'C', 'E']
Following additional clarification from the OP regarding the requirements:
However, I notice I forgot to mention a requirement. A combination
always needs to have exactly 1 letter of each of the major lists. So
in this example, there must be one out of A,B,C, another one out of
A,B,C and on out of D, E.
I have decided to leave my original answer, and add this one alongside it for the slightly different use case.
Still preprocess the input data, although less heavily - this time a list of dictionaries (again with sets as dictionary values):
data_in = [
[{'A': [35, 64, 72]}, {'B': [42, 55, 23]}, {'C': [17, 23, 55]}],
[{'A': [35, 64, 72]}, {'B': [42, 55, 23]}, {'C': [17, 23, 55]}],
[{'D': [72]}, {'E': [42]}]
]
target_list = [35, 64, 72, 42, 17, 23, 55]
data = []
for sublist in data_in:
dct = {}
for dct_in in sublist:
dct.update({k: set(v) for k, v in dct_in.items()})
data.append(dct)
target = set(target_list)
print(data)
# [{'A': {64, 72, 35}, 'B': {42, 23, 55}, 'C': {17, 55, 23}}, {'A': {64, 72, 35}, 'B': {42, 23, 55}, 'C': {17, 55, 23}}, {'D': {72}, 'E': {42}}]
print(target)
# {64, 35, 72, 42, 17, 55, 23}
And now again a recursive solution, but a slightly different one from before:
def find_combos(target, data):
for k, v in data[0].items():
if not (v - target):
remaining_data = data[1:]
remaining_target = target - v
if remaining_data:
for lst in find_combos(remaining_target, remaining_data):
yield [k] + lst
elif not remaining_target:
yield [k]
for combo in find_combos(target, data):
print(combo)
This gives:
['A', 'C', 'E']
['C', 'A', 'E']
If you want to avoid "duplicates" (only looking at the keys here - this is dependent on the same keys having the same associated values in the input), you could do something like this:
combos_dict = {tuple(sorted(combo)): combo
for combo in find_combos(target, data)}
uniq_combos = list(combos_dict.values())
print(uniq_combos)
which gives:
[['A', 'C', 'E']]
Final update - further modification to deal with further new information that repeats are also possible in the input lists. Hence use counts dictionaries instead of sets. To implement this:
In preprocessing the input data, use from collections import Counter and replace set with Counter in the two places where it appears, giving:
data = [{'A': Counter({35: 1, 64: 1, 72: 1}), 'B': Counter({42: 1, 55: 1, 23: 1}), 'C': Counter({17: 1, 23: 1, 55: 1})}, {'A': Counter({35: 1, 64: 1, 72: 1}), 'B': Counter({42: 1, 55: 1, 23: 1}), 'C': Counter({17: 1, 23: 1, 55: 1})}, {'D': Counter({72: 1}), 'E': Counter({42: 1})}]
target = Counter({35: 1, 64: 1, 72: 1, 42: 1, 17: 1, 23: 1, 55: 1})
Then replace
if not (v - target):
with
if all(target.get(kk, 0) >= vv for kk, vv in v.items()):
Finally, replace
remaining_target = target - v
with
remaining_target = target.copy()
for kk, vv in v.items():
remaining_target[kk] -= vv
if remaining_target[kk] == 0:
del remaining_target[kk]

How can I return the values with the same length in a dictionary?

Currently, I have the following dictionary, with a key, and values of type dictionary as well:
db = {
'john' : {'a': 13, 'b': 64, 'c': 43},
'eric' : {'a': 63, 'b': 12},
'kek' : {'a': 43, 'b': 37, 'c': 83, 'd': 87},
'rick' : {'a': 77, 'b': 66, 'c': 44},
'alex' : {'a': 44, 'b': 99, 'c': 22}
}
How can I return a set of all the keys with the same number of items in the value part? In the dictionary above, the keys: john, rick, alex all have the same amount of keys. So the output would include these.
Expected Output:
same = {john, rick, alex}
Here is my code so far, i'm not sure how to store the current length:
db = {
'john': {'a': 13, 'b': 64, 'c': 43},
'eric': {'a': 63, 'b': 12},
'kek': {'a': 43, 'b': 37, 'c': 83, 'd': 87},
'rick': {'a': 77, 'b': 66, 'c': 44},
'alex': {'a': 44, 'b': 99, 'c': 22}
}
def maximum(db):
same = {}
for key, value in db.items():
for values in value:
if len(values) == 'something':
pass
maximum(db)
Try this, You can find your desires in the result:
from itertools import groupby
result = []
for i,j in groupby(sorted(db.items(), key = lambda x:len(x[1])), lambda x:len(x[1])):
result.append({i:[k[0] for k in j]})
then the result will be:
[{2: ['eric']}, {3: ['john', 'rick', 'alex']}, {4: ['kek']}]
keys are the len of items and values are those which has that length.
I have your output when I enter the following code:
def maximum(db):
for key, value in db.items():
if len(value) == 3:
print(key)
maximum(db)
Instead of print() enter whatever suits your needs of course.
Since OP says thats he requires the keys which have values of the same length, so that length must be the most frequent occuring length (ofcourse this is an assumption, but OP has not clarified that. There could be, for instance two sets ot values, having length either 2 or 3, so we should output keys corresponding to which value lengths? 2 or 3?)
db = {'john': {'a': 13, 'b': 64, 'c': 43},
'eric': {'a': 63, 'b': 12},
'kek': {'a': 43, 'b': 37, 'c': 83, 'd': 87},
'rick': {'a': 77, 'b': 66, 'c': 44},
'alex': {'a': 44, 'b': 99, 'c': 22} }
from collections import Counter
elem_len = [len(r) for k,r in db.items()]
c = Counter(elem_len)
most_common_length = c.most_common(1)[0][0]
print(most_common_length)
3
elements = [k for k,r in db.items() if len(r)==most_common_length]
print(elements)
['john', 'rick', 'alex']
Try this:
db = {51: {'a': 13, 'b': 64, 'c': 43}, 64: {'a': 63, 'b': 12}, 87: {'a': 43, 'b': 37, 'c': 83, 'd': 87}, 91: {'a': 77, 'b': 66, 'c': 44}, 99: {'a': 44, 'b': 99, 'c': 22} }
def maximum(db):
count_map = {}
for key, value in db.items():
if len(value.keys()) in count_map.keys():
count_map[len(value.keys())].append(key)
continue
count_map[len(value.keys())] = [key,]
countwise_list = list(count_map.values())
countwise_list.sort(key=(lambda x: len(x)), reverse=True)
return countwise_list[0]

Combining and ordering dictionaries in python

If I have multiple dictionaries like so:
dict1 = {Jamal: 10, Steve: 20}
dict2 = {Frank: 200, Steve: 30}
dict3 = {Carl: 14, Jamal: 26}
How would I combine them and order them in descending order of numbers without overwriting any values so that it shows something like:
Frank: 200, Steve: 30, Jamal: 26, Steve: 20, Carl: 14, Jamal: 10
There are two Steve from dict1, dict2. Mapping types does not allow duplicated keys.
You need to use sequences type (like list, tuple, ..).
>>> dict1 = {'Jamal': 10, 'Steve': 20}
>>> dict2 = {'Frank': 200, 'Steve': 30}
>>> dict3 = {'Carl': 14, 'Jamal': 26}
>>>
>>> import itertools
>>> it = itertools.chain.from_iterable(d.items() for d in (dict1, dict2, dict3))
>>> ', '.join('{}: {}'.format(*x) for x in sorted(it, key=lambda x: x[1], reverse=True))
'Frank: 200, Steve: 30, Jamal: 26, Steve: 20, Carl: 14, Jamal: 10'
You can not create a dictionary with duplicate keys, use OrderedDict with dict.setdefault method to put the relative values in a list :
dict1 = {'Jamal': 10, 'Steve': 20}
dict2 = {'Frank': 200, 'Steve': 30}
dict3 = {'Carl': 14, 'Jamal': 26}
from collections import OrderedDict
from itertools import chain
from operator import itemgetter
d = OrderedDict()
for key, value in sorted(chain.from_iterable([dict1.items(),dict2.items(),dict3.items()]), key=itemgetter(1),reverse=True):
d.setdefault(key,[]).append(value)
print d
OrderedDict([('Frank', [200]), ('Steve', [30, 20]), ('Jamal', [26, 10]), ('Carl', [14])])
Or just sorted like following :
print sorted(chain.from_iterable([dict1.items(),dict2.items(),dict3.items()]), key=itemgetter(1),reverse=True)
[('Frank', 200), ('Steve', 30), ('Jamal', 26), ('Steve', 20), ('Carl', 14), ('Jamal', 10)]

Categories