Отображение только самого высокого из 3 последних результатов, сохраненных в файле .txt

Я пытаюсь изучить основы использования Python для личного проекта.

Я создал программу, которая задает пользователю десять географических вопросов, а затем сохраняет их оценку в .txt-файл в этом формате:

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

Затем я создал новую программу, которая может использоваться для отображения наивысшего балла каждого человека в алфавитном порядке:

 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]) 

Я хотел бы изменить этот код, чтобы он выводил только самые высокие из трех последних результатов. Например, из приведенного файла .txt показатель Joeseph будет отображаться как:

 Joeseph - 5 

Программа должна опускать всех, кроме 3 самых последних баллов от каждого человека.

5 Solutions collect form web for “Отображение только самого высокого из 3 последних результатов, сохраненных в файле .txt”

Вместо того, чтобы отслеживать самый высокий балл в вашем первом цикле, просто отслеживайте последние три балла:

 user_scores = {} for line in scores: name, score = line.rstrip('\n').split(' - ') score = int(score) if name not in user_scores: user_scores[name] = [] # Initialize score list user_scores[name].append(score) # Add the most recent score if len(user_scores[name]) > 3: user_scores[name].pop(0) # If we've stored more than 3, get rid of the oldest 

Затем, в конце, пройдите и получите максимум:

 user_high_scores = {} for name in user_scores: user_high_scores[name] = max(user_scores[name]) # Find the highest of the 3 most recent scores 

Затем вы можете распечатать высокие баллы, как и раньше:

 for name in sorted(user_scores): print(name, '-', user_scores[name]) 

Это должно сделать трюк

 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])) 

Используя defaultdict, мы избегаем уродливости при проверке. Deque хранит только последние 3 балла. Обратите внимание, что это работает, даже если у пользователя меньше 3 баллов.

Если вам нужны отсортированные рекорды, последний цикл можно заменить на:

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

Во-первых, поскольку вы хотите только прочитать последние 3 балла, начинайте с конца файла и читайте назад.

 user_scores = {} for line in reversed(open("scores.txt").readlines()): name, score = line.rstrip('\n').split(' - ') score = int(score) # first, only update if the name exists # and there is less than 3 scores already if name in user_scores and len(user_scores[name]) < 3: user_scores[name].append(score) # this is a new record, so lets just add it # make the value a list so we can easily just add a score to it if name not in user_scores: user_scores[name] = list((score,)) 

теперь у нас есть указатель пользователей, каждый из которых имеет список из трех последних оценок. Давайте получим их лучшие результаты.

 best_scores = {} for name in sorted(user_scores): # get the highest score in the list. best_scores[name] = max(user_scores[name]) 

теперь мы можем просто распечатать максимальные баллы пользователя по мере необходимости

 for name in sorted(best_scores): print("{} - {}".format(name, best_scores[name])) 

Если я правильно понимаю, вывод должен быть:

 Joeseph - 5 Joeseph - 3 Joeseph - 4 

Вот как я бы решил проблему

 with open("highscores.txt", "r+") as file: file.seek(0) scores = file.readlines() # generate list of [name, score] pairs instead of strings scores_pairs = [score.strip().split(' - ') for score in scores] # configure output lookup_name = 'Joeseph' RECENT_SCORES_LIMIT = 3 # indicates how many scores were added recent_scores_count = 0 # scores will be stored here most_recent_scores = [] # we need to reverse list to search it from the end for score in reversed(scores_pairs): name = score[0] # if current score is if interested person and scores limit not exceeded... if name == lookup_name and recent_scores_count < RECENT_SCORES_LIMIT: # add current score to list most_recent_scores.append(score) recent_scores_count += 1 # to display scores in historical order we need to reverse list again for name, score in reversed(most_recent_scores): # better use .format method to produce strings using python variables print('{} - {}'.format(name, score)) 

Обычный способ сделать это – использование collections.deque

 from collections import defaultdict, deque d = defaultdict(lambda: deque(maxlen=3)) # some dict d where d['new key'] -> d['new key'] = deque(maxlen=3) with open('path/to/scores.txt') as scores: for line in scores: name, score = line.split(" - ") d[name].append(int(score)) for player, scores in sorted(d.items()): print("{} - {}".format(player, max(scores)) # {"James":deque([2,6,11]), -> "James - 11" # {"Susan":deque([3,1,2])} -> "Susan - 3" 
  • Regex для выделения вложенных шаблонов
  • Почему диапазон (0) == range (2, 2, 2) True в Python 3?
  • Поведение функции «round» в Python
  • Загрузка файла с помощью Tornado
  • Переопределить свойство только для чтения с столбцом только для чтения, который получает то же значение
  • Практическое использование операторов реверсивного набора в Python
  • Есть ли способ вернуть пользовательское значение min и max в Python?
  • Python 3.x: альтернативная реализация pprint
  • Печать в той же строке, шаг за шагом
  • Python - Отмена печати ()
  • Python - класс __hash__ и установить
  • Python - лучший язык программирования в мире.