user5637300
user5637300

Reputation: 33

How to sort this float list of numerical values in ascending order?

I have been able to import 3 scores (or numbers) for each person in my CSV file and have it work out the average of the three scores for each person but what I need to do next is sort the list of averages shown in the output from high to low. I have searched everywhere and have received 'Float' errors with everything I try.

from collections import defaultdict, deque
with open("highscores.csv", "r+")as file:
    file.seek(0)
    scores = file.readlines()
user_scores = defaultdict(lambda:deque(maxlen=3))
for line in scores:
    name, score = line.rstrip('\n').split(',')
    score = int(score)
    user_scores[name].append(score)

for name in user_scores:
    avg = (user_scores[name])
    x = sorted(avg)
    avg2 = sum(x) / float(len(x))
    print(name, avg2)

Output:

Odis 22.0
Vance 20.0
John 26.0
Marinda 25.0
Shenita 18.0
Marquitta 24.0
Concepcion 17.0
Robby 23.0
Valda 19.0
Ernesto 21.0
Jack 5.0

My CSV file looks like this :

Jack    4
Jack    5
Jack    6
Concepcion  7
Shenita 8
Valda   9
Vance   10
Ernesto 11
Odis    12
Robby   13
Marquitta   14
Marinda 15
John    16
Concepcion  17
Shenita 18
Valda   19
Vance   20
Ernesto 21
Odis    22
Robby   23
Marquitta   24
Marinda 25
John    26
Concepcion  27
Shenita 28
Valda   29
Vance   30
Ernesto 31
Odis    32
Robby   33
Marquitta   34
Marinda 35
John    36

Upvotes: 3

Views: 840

Answers (3)

Jens Grabarske
Jens Grabarske

Reputation: 755

The line where you sort avg is unnecessary - after all these are the scores of a single person and it doesn't matter in which order you sum them. What you want to do is to sort all the entries once all the averages are calculated, so you need to collect those. If you want them to be sorted according to their averages, use a tuple with the average as the first field, that way sorted will do exactly what you want:

# The list that will hold the pairs of
# average score and name
avgs = []

# Your initial loop
for name in user_scores:
    x = user_scores[name]

    # Just collect the pair
    avgs.append((sum(x) / float(len(x)), name)

# Now sort it
avgs = sorted(avgs)

# Print it
for avg, name in avgs:
    print (name, avg)

However, a much more Pythonesque way of doing it is with list comprehensions:

# A function for the average
def average(lst):
    return sum(lst) / float(len(lst))

# The averages as list comprehension    
avgs = sorted((average(scores), name)
              for name, scores in user_scores.items())

# Print it
for avg, name in avgs:
    print (name, avg)

This assumes that you are using Python 3, for Python 2 use iteritems() or viewitems()

Upvotes: 3

200_success
200_success

Reputation: 7582

Assuming Python 3…

In your second for loop, you can't possibly get them printed in the desired order if you're printing them while you're still calculating the averages. You need to split it up into two phases.

Calculate the average scores:

avg_user_scores = {
    user: sum(map(float, scores))/len(scores)
    for user, scores in user_scores.items()
}

Then print them, sorted in descending order:

for name, score in sorted(avg_user_scores.items(), key=itemgetter(1), reverse=True):    
    print(name, score)

operator.itemgetter(1) is a way to fetch the second element of a tuple (i.e. lambda t: t[1]) — which is the average score.


The entire program:

from collections import defaultdict, deque
from operator import itemgetter

user_scores = defaultdict(lambda: deque(maxlen=3))
with open('highscores.csv') as file:
    for line in file:
        name, score = line.split(',')
        user_scores[name].append(float(score))
avg_user_scores = {
    user: sum(scores) / len(scores)
    for user, scores in user_scores.items()
}
for name, score in sorted(avg_user_scores.items(), key=itemgetter(1), reverse=True):    
    print(name, score)

Upvotes: 1

sikez
sikez

Reputation: 85

Average the three scores for each person. Place the values into a dictionary (the key will be the person). Call the sorted() method.

Upvotes: 0

Related Questions