Reputation: 1
Write a Python function maxaggregate(l) that takes a list of pairs of the form (name,score) as argument, where name is a string and score is an integer. Each pair is to be interpreted as the score of the named player. For instance, an input of the form [('Kohli',73),('Ashwin',33),('Kohli',7),('Pujara',122),('Ashwin',90)] represents two scores of 73 and 7 for Kohli, two scores of 33 and 90 for Ashwin and one score of 122 for Pujara. Your function should compute the players who have the highest aggregate score (aggegrate = total, so add up all scores for that name) and return the list of names of these players as a list, sorted in alphabetical order. If there is a single player, the list will contain a single name.
For instance:
maxaggregate([('Kohli',73),('Ashwin',33),('Kohli',7),('Pujara',122),('Ashwin',90)])
should return:
['Ashwin']
because the aggregate score of Kolhi is 80, of Ashwin is 123 and of Pujara is 122, of which 123 is the highest.
def maxaggregate(l):
d = {}
for i in l:
if i[0] in d:
d[i[0]] += i[1]
else:
d[i[0]] = i[1]
m = max(list(d.values()))
x = []
for i in d:
if d[i] == m:
x.append(i)
return sorted(x)
Upvotes: 0
Views: 956
Reputation: 7887
I would probably use a defaultdict
:
from collections import defaultdict
def maxaggregate(lst):
# If a key is not in the dict it will
# default the value for that key to 0 (the default int).
d = defaultdict(int)
# Sum up the scores
for name, score in lst:
d[name] += score
# Return the max score by iterating
# over the defaultdict's items and finding
# the max score (the 2nd element
# in the item is the score thus the x[1]).
return max(d.items(), key=lambda x: x[1])
r = maxaggregate([('Kohli',73),('Ashwin',33),('Kohli',7),('Pujara',122),('Ashwin',90)])
print(r) # ('Ashwin', 123)
Upvotes: 2
Reputation: 1598
You can iterate over the list, create a dict to keep the scores and add up the scores by name. Then keeping note of the highest score you find with the associated name.
def maxaggregate(scores):
agg_results = {}
max_name = None
max_val = None
for name, score in scores:
score += agg_results.get(name, 0) # Add up the score
agg_results[name] = score # Save it in the dict
if max_val is None or max_val < score: # Compare scores
max_val = score
max_name = name
return name
print(maxaggregate([('Kohli',73),('Ashwin',33),('Kohli',7),('Pujara',122),('Ashwin',90)]))
Returns: Ashwin
This solution only iterates over the list once.
Upvotes: 1
Reputation: 73460
You can do the following, using a collections.Counter
and itertools.takewhile
:
from collections import Counter
from itertools import takewhile
def maxaggregate(l):
c = Counter()
for k, v in l:
c[k] += v
mc = c.most_common()
max_count = mc[0][1]
return sorted(name for name, _ in takewhile(lambda i: i[1] == max_count, mc))
Upvotes: 0