1

I have some data which is a list of scores for each of various users. The following code finds the maximum value of the last three scores for the user (sorted so the user with the lowest score is shown first), and print that out:

dlist = {c:max(d[c][-3:]) for c in d} #max for each user from last 3
itmlist = sorted(dlist.items(), key=lambda x: x[1]) #sort items
for z in itmlist:
  print('{}: {} '.format(z[0], z[1])) #print user-by-user

I'm trying to modify this to use sum(l)/len(l) in order to find the average value of the last three scores for each user, and then sort this to print the lowest user averages in order, but have hit a dead end.

Can anyone point me in the right direction?

--

EDIT:

This is the code used to generate the list. I am using a text file containing data containing scores in a format like:

Bob:2
John:7

This is then read using this:

[view post history]

DasKapital
  • 73
  • 7
  • 1
    Can you provide a test d and its expected output? – igon Apr 27 '15 at 20:16
  • 1
    When you are using `sum(l)/len(l)`, it will implicitly return an `int` which may lose the precision of the calculation, kindly provide the sample input to make the problem clearer? Define the `d` – ZdaR Apr 27 '15 at 20:16
  • 1
    `sum(l)/len(l)` should be the same for all the items, how can you sort by it? (or in other words, I guess I don't understand what you're trying to do here) – Nir Alfasi Apr 27 '15 at 20:17
  • 1
    In Python 3, `/` returns a `float` when necessary, and judging by the `print()` function this looks like Python 3. – TigerhawkT3 Apr 27 '15 at 20:17
  • I've edited my post to show what I am using to generate the initial list. – DasKapital Apr 27 '15 at 20:20
  • Where does the average comes from ?, There are single integer values for each keys then what is the significance of average ? – ZdaR Apr 27 '15 at 20:20
  • 1
    I wish to obtain the average values from the last three scores of each user, and then print them out next to the user's name in lowest-to-highest order (which is already happening, just for the _maximum values_). – DasKapital Apr 27 '15 at 20:22
  • An aside: use `collections.defaultdict` for `d` – smci Apr 27 '15 at 20:23
  • 2
    By the way, I'd recommend using clearer variable names, like `students` instead of `c`, `all_scores` instead of `d`, `name` instead of `x`, `scores` instead of `y`, and so on. – TigerhawkT3 Apr 27 '15 at 20:29

4 Answers4

1

The question is a bit unclear, So I have made some assumptions, tell me if I am wrong somewhere?

d = {"bob":[1,2,3,4], "anmol":[5,4,3,2,1], "jhon":[3,2,1,8,7]}

new_sorted_list = sorted(d.keys(), key=lambda x: sum(d[x][-3:])/3)

print new_sorted_list

>>> ['anmol', 'bob', 'jhon']

for record in new_sorted_list:
    print record+"  : "+str(sum(d[record][-3:])/3.0)

>>> anmol  : 2.0
    bob  : 3.0
    jhon  : 5.33333333333
ZdaR
  • 22,343
  • 7
  • 66
  • 87
0

A defaultdict, deque and statistics.mean will do what you want:

from collections import defaultdict, deque
from statistics import mean

# store maximum three scores using a defaultdict for repeated keys
d = defaultdict(lambda: deque(maxlen=3))

for q in range(1, 4):
    with open('Group{}.txt'.format(q), 'r') as f:
        for record in f:
            x, y = record.split(':')
            d[x].append(int(y))

# sort by values
srt = sorted(d.items(), key=lambda x: x[1])

# print name and mean from sorted list
for name,scores in srt:
    print('{}: {} '.format(name, mean(scores))) #print user-by-user

If you want the values to be set to the mean update the dict before sorting:

for name, scores in d.items():
    d[name] = mean(scores)


for name, mn in sorted(d.items(), key=lambda x: x[1]):
    print('{}: {} '.format(name, mn))

You don't need to calculate the average to sort as all your values will have length 3 so the list with the highest total score is going to have the highest average.

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
0
>>> d = {'Bob':[2,4,4,5], 'John':[7,5,5,1]}
>>> dlist = {c:max(d[c][-3:]) for c in d}
>>> dlist2 = {user:sum(scores[-3:])/3 for user,scores in d.items()}
>>> print(*(': '.join(map(str, [person, dlist2.get(person)])) for person in sorted(dlist2, key=dlist.get)), sep='\n')
John: 3.6666666666666665
Bob: 4.333333333333333
TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
-2

If you only care about the average of the last three scores:

dlist = {c:sum(d[c][-3:]) for c in d} #sum of last three scores for each user
itmlist = sorted(dlist.items(), key=lambda x: x[1]) #sort items on score
for z in itmlist:
  print('{}: {} '.format(z[0], z[1]/3)) #print user-by-user
igon
  • 3,016
  • 1
  • 22
  • 37