如何在Python(Pygame)中用逗号分隔值(.txt)文件显示前10个高分

时间:2013-10-24 20:16:06

标签: python arrays

我正在为我的游戏创建一个高分榜。 它以下列格式将值附加到.txt文件:

5.234,0,0,5234
6.345,1,1,8345
1.649,0,1,2649
2.25,0,1,3250

...等

我想阅读前10个分数(分数是每行的第4个值) 并将它们输出到屏幕上。我尝试过使用here信息,但我无法理解它。输出它们的最佳方法是什么?

我知道您可以使用

分割值
for line in f:
    Array = line.split(',')

非常确定如果我将它们放在已排序的2D数组或等效的

中,我可以管理输出

5 个答案:

答案 0 :(得分:2)

使用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)

如果你只想要前10名:

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)

从另一个答案的评论中,您实际上想要获得每一行中的所有四个值。因此,您不必只读取每一行的最后一列,而是需要读取整行。此外,您可能希望将第一列转换为浮点数,其余部分转换为整数,这比仅在每行中的所有列上映射函数要复杂一些。同时,nlargestsorted将按第一列进行比较,但您希望它按最后一列进行比较,这意味着您需要提供key function。虽然自己写一个并不困难,但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))

此代码的唯一问题是列顺序的知识在您的代码中隐式分散。如果您有一个dicts列表,而不是列表列表,这将允许您按名称访问值。 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,除timescore之外的任何内容等等。另一方面,代码更冗长,有些人更难找到字典理解阅读比列表理解/生成器表达式,所以...这是一个品味问题,这是否是一个改进。

答案 1 :(得分:1)

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)

答案 2 :(得分:1)

虽然不是严格要求,但我会使用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

当然,您的样本数据实际上没有足够的总得分能够显示前十名。

答案 3 :(得分:0)

使用Python的csv库,这非常简单。

import csv
with open('scores.txt', 'r') as csvfile:
    scorereader = csv.reader(csvfile, delimiter=',', quotechar='"')
    for row in scorereader:
        print ', '.join(row)

答案 4 :(得分:0)

with open('high_scores.txt') as f:
    sorted([line.strip().split(',') for line in f], key=lambda x: int(x[3]), \
             reverse=True)[:10]