Displaying only the highest of a person's 3 most recent scores, saved in a .txt file
Question: I am trying to learn the fundamentals of using Python for a personal project.

I have created a program which asks the user ten geographical questions, and
then saves their score to a .txt file, in this format:

    
    
    Imran - 8
    Joeseph - 10
    Test1 - 6
    Test2 - 4
    Joeseph - 5
    Aaron - 4
    Test1 - 1
    Zzron - 1
    Joeseph - 3
    Test1 - 10
    Joeseph - 4
    

I then created a new program, which can be used to display the highest score
of each person in alphabetical order:

    
    
    with open("highscores.txt", "r+")as file:
        file.seek(0)
        scores = file.readlines()
    
    user_scores = {}
    for line in scores:
        name, score = line.rstrip('\n').split(' - ')
        score = int(score)
        if name not in user_scores or user_scores[name] < score:
            user_scores[name] = score
    
    for name in sorted(user_scores):
        print(name, '-', user_scores[name])
    

I would like to alter this code, such that it only outputs the highest of a
person's 3 most recent scores. For example, from the .txt file given,
Joeseph's score would be displayed as:

    
    
    Joeseph - 5
    

The program should omit all but the 3 most recent scores from each person.


Answer: This should do the trick

    
    
    from collections import defaultdict, deque    
    with open("highscores.txt", "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:
        print(name, '-', max(user_scores[name]))
    

By using defaultdict, we avoid ugly in checking. The deque keeps only the last
3 scores. Note this works even if the user has less than 3 scores.

If you need the high scores sorted, than the last loop can be replaced with:

    
    
    user_scores=[(max(user_scores[user]), user) for user in user_scores]
    for score, name in sorted(user_scores):
        print(name, '-', score)
    

