Canadian1010101 Canadian1010101 - 7 months ago 18
Python Question

Using more than the last 3 scores to analyse data; also repeating analysis?

I've calculated the average and the highest score per name. However. If I have the following values saved in a text file, this is what the results show:

matt 5
matt 2
matt 3
andy 1
andy 2
andy 3
andy 4
matt 4
matt 's average from the last 3 scores is 4.0
andy 's average from the last 3 scores is 4.0
matt 's average from the last 3 scores is 4.0
andy -'s best score is 4
matt -'s best score is 5


It seems to be repeating the first name (i.e. matt's average twice and looping over it?)
Also it is producing the data based on each of the scores, not just the last 3?

user_scores = {}
for line in reversed(open("Class1.txt").readlines()):
name, score = line.split()
score = int(score)

Answer

It's an indentation error. You want this block below to be on the first indentation level:

for name in sorted(user_scores):
    # get the highest score in the list
    average = sum(user_scores[name]) /float(len(user_scores[name]))   
    print(name, "'s average from the last 3 scores is", average)

Also, there are many places where your code is written in a bad way. Here's an optimization:

user_scores = {}

# 'with' will automatically closes the file after leaving its code block:
with open("Class1.txt") as scorefile:  

    for line in reversed(scorefile.readlines()):  
        name, score = line.split()

        # nested if inside if/else is better than if-and plus if not:
        if name in user_scores:
            if len(user_scores[name]) < 3:
                user_scores[name].append(int(score))
        else:
            user_scores[name] = [int(score)]

# If you want to sort by the numeric value, replace 'sorted(user_scores)' with 
# 'sorted(user_scores, key=lambda k: user_scores[k])':
for name in sorted(user_scores):
    # in Python 3 the '/' operator always returns the appropriate format.
    # to get a pure integer division without decimal places, you would use '//'.
    # Therefore no need for the float(...) conversion.
    average = sum(user_scores[name]) / len(user_scores[name])
    # str.format(...) is more flexible than just printing multiple items:
    print("{}'s average from the last 3 scores is {}".format(name, average))

# No need to store another dictionary with best scores.
# If you want to sort by the numeric value, replace 'sorted(user_scores)' with 
# 'sorted(user_scores, key=lambda k: user_scores[k])':
for name in sorted(user_scores):
    print("{}'s best score is {}".format(name, max(user_scores[name])))