[英]How to display top 10 highscores from a comma separated value (.txt) file in Python (Pygame)
我正在为我的游戏创建一个高分表。 它将值以以下格式附加到.txt文件:
5.234,0,0,5234
6.345,1,1,8345
1.649,0,1,2649
2.25,0,1,3250
...等等
我想读取前10个得分(得分是每行的第4个值)并将其输出到屏幕上。 我尝试使用这里的信息,但是我无法理解。 输出它们的最佳方法是什么?
我知道您可以使用
for line in f:
Array = line.split(',')
我很确定如果我将它们放在排序的2D数组或等效数组中,就可以管理输出
使用csv
模块会更容易。 例如:
with open('highscores.txt', 'rb') as f:
reader = csv.reader(f)
scores = list(reader)
现在, scores
将是10个列表的列表,每个列表都有4个值。
如果需要,可以对split
执行相同的操作,但是必须确保正确理解所有详细信息,例如将换行符从每一行的末尾剥离(在琐碎的CSV中,详细信息会变得更加复杂)文件):
with open('highscores.txt', 'rb') as f:
scores = [line.strip().split(',') for line in f]
现在,您可以对每个步骤使用单个理解或函数调用来一次转换列出的一个步骤。 这种“声明式编程”,您只需要对值说些什么,而不用编写循环并交错所有步骤,就可以使您的生活变得更加轻松。
如果只需要最后一列,则可以理解:
with open('highscores.txt', 'rb') as f:
reader = csv.reader(f)
scores = [row[-1] for row in reader]
如果要将它们转换为整数:
with open('highscores.txt', 'rb') as f:
reader = csv.reader(f)
scores = (row[-1] for row in reader)
intscores = [int(score) for score in scores]
…尽管在这种情况下,将两个步骤合并在一起很简单:
with open('highscores.txt', 'rb') as f:
reader = csv.reader(f)
scores = [int(row[-1]) for row in reader]
如果希望它们以相反的顺序(从最高到最低)排序:
with open('highscores.txt', 'rb') as f:
reader = csv.reader(f)
scores = (int(row[-1]) for row in reader)
topscores = sorted(scores, reverse=True)
如果您只想要前十名:
with open('highscores.txt', 'rb') as f:
reader = csv.reader(f)
scores = (int(row[-1]) for row in reader)
topscores = sorted(scores, reverse=True)
top10 = topscores[:10]
通过使用heapq
模块,可以使最后一步更有效,但更为复杂:
with open('highscores.txt', 'rb') as f:
reader = csv.reader(f)
scores = (int(row[-1]) for row in reader)
top10 = heapq.nlargest(10, scores)
从对另一个答案的评论中,您实际上希望获得每行中的所有四个值。 因此,您不仅需要阅读每一行的最后一列,还需要阅读整行。 另外,您可能想将第一列转换为浮点数,将其余列转换为整数,这比仅将函数映射到每一行中的所有列要复杂得多。 同时, nlargest
或sorted
将按第一列进行比较,但是您希望它按最后一列进行比较,这意味着您需要提供键函数 。 尽管自己写一个并不难,但itemgetter
已经完全itemgetter
您的要求。
with open('highscores.txt', 'rb') as f:
reader = csv.reader(f)
def convert_row(row):
return [float(row[0])] + [int(value) for value in row[1:]]
scores = (convert_row(row) for row in reader)
top10 = heapq.nlargest(10, scores, key=operator.itemgetter(-1))
for record in top10:
print('time: {} | moves: {} | penalties: {} | score: {}'.format(*record))
此代码的唯一问题是,列顺序的知识有点隐式地散布在整个代码中。 如果您有字典列表而不是列表列表,则可以按名称访问值。 使用DictReader
,您可以执行以下操作:
with open('highscores.txt', 'rb') as f:
reader = csv.DictReader(f, fieldnames=('time', 'moves', 'penalties', 'score'))
def convert_row(row):
return {k: float(v) if k == 'time' else int(v) for k, v in row.items()}
scores = [convert_row(row) for row in reader]
top10 = heapq.nlargest(10, scores, key=operator.itemgetter('score'))
for record in top10:
print('time: {time} | moves: {moves} | penalties: {penalties} | score: {score}'
.format(**record))
format
函数中不再有0、1,-1或隐式排序; 现在一切都被现场的名字- time
,任何东西,但time
, score
,等等。另一方面,代码是很多更详细的,有些人觉得字典内涵难度比列表理解/发电机表达式读取,所以......这是口味的问题,这是否有所改善。
heapq.nlargest
正是为此任务而设计的。 让您的示例遵循以下代码可输出前2个得分。 根据您的需求进行修改
import heapq
lst = ['5.234,0,0,5234',
'6.345,1,1,8345',
'1.649,0,1,2649',
'2.25,0,1,3250']
scores = map(int, (l.split(',')[3] for l in lst))
print heapq.nlargest(2, scores)
尽管不是严格要求,但我将使用csv
模块:
import csv
with open('scores.txt', 'rb') as csvfile:
values = [[float(row[0])] + map(int, row[1:]) for row in csv.reader(csvfile)]
top_ten = sorted(values, reverse=True, key=lambda v: v[3])[:10]
for row in top_ten:
print("time: {0:.3f} | moves: {1:,d} | "
"penalties: {2:,d} | score: {3:,d}".format(*row))
输出:
time: 6.345 | moves: 1 | penalties: 1 | score: 8,345
time: 5.234 | moves: 0 | penalties: 0 | score: 5,234
time: 2.250 | moves: 0 | penalties: 1 | score: 3,250
time: 1.649 | moves: 0 | penalties: 1 | score: 2,649
当然,样本数据中实际上没有足够的总分来显示前十名。
使用用于Python的csv库,这非常简单。
import csv
with open('scores.txt', 'r') as csvfile:
scorereader = csv.reader(csvfile, delimiter=',', quotechar='"')
for row in scorereader:
print ', '.join(row)
with open('high_scores.txt') as f:
sorted([line.strip().split(',') for line in f], key=lambda x: int(x[3]), \
reverse=True)[:10]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.