你绝对不想要这里的字典。字典的重点是能够将键映射到值,而无需任何排序。你想要的是一个排序列表。你已经明白了。
好吧,正如 Tamás 指出的那样,您实际上得到了一个按球员姓名排序的列表,而不是分数。最重要的是,您希望按向下顺序排序,而不是向上排序。你可以使用 decorate-sort-undecorate 模式,或者一个键函数,或者其他什么,但是你需要做一些事情。此外,您已将其放在名为 的变量中list
,这是一个非常糟糕的主意,因为这已经是list
类型的名称。
无论如何,您可以使用标准库中的模块来确定是否将某些内容添加到 sortedlist
中,以及在哪里插入。bisect
但是使用类似的东西可能更简单SortedCollection
or blist
。
这是一个例子:
highscores = SortedCollection(scores, key=lambda x: -x[3])
现在,当你完成游戏时:
highscores.insert_right((player, a, b, newscore, time1))
del highscores[-1]
而已。如果您实际上不在前 10 名,您将被添加到第 11 名,然后被删除。如果您在前 10 名中,您将被添加,而旧的 #10 现在将成为 #11 并被删除。
如果您不想像以前的街机游戏那样用 10 个假分数预先填充列表,只需将其更改为:
highscores.insert_right((player, a, b, newscore, time1))
del highscores[10:]
现在,如果已经有 10 个分数,当你被添加时,#11 将被删除,但如果只有 3 个,则什么都不会被删除,现在有 4 个。
同时,我不确定您为什么要将新分数写入pickle
文件,然后再读回相同的内容。您可能希望在将高分添加到列表之前进行读取,然后在之后进行写入添加它。
您还问如何“美化列表”。嗯,这有三个方面。
首先,在代码中,(player, a, b, c, time1)
意义不大。当然,为变量提供更好的名称会有所帮助,但最终您仍然会归结为这样一个事实,即在访问列表时,您必须entry[3]
获得分数或entry[4]
时间。
至少有三种方法可以解决这个问题:
- 存储 s 的一个
list
(或SortedCollection
)dict
而不是tuple
s。代码变得更加冗长,但更具可读性。你写{'player': player, 'height': a, 'weight': b, 'score': c, 'time': time1}
,然后在访问列表时,你做entry['score']
而不是entry[3]
.
- 使用
namedtuple
s 的集合。现在你实际上可以只插入ScoreEntry(player, a, b, c, time1)
,或者你可以插入ScoreEntry(player=player, height=a, weight=b, score=c, time=time1)
,以在给定的情况下更具可读性,并且它们的工作方式相同。您可以访问entry.score
or as entry[3]
,再次使用更具可读性的那个。
- 为分数条目编写一个明确的类。这与上一个非常相似,但是要编写更多代码,并且您不能再进行索引访问,但从好的方面来说,您不必了解
namedtuple
.
其次,如果你只是print
条目,它们看起来像一团糟。处理这个问题的方法是字符串格式化。而不是print scores
,你做这样的事情:
print '\n'.join("{}: height {}, weight {}, score {} at {}".format(entry) for entry in highscores)
如果您使用 a class
ornamedtuple
而不仅仅是 a tuple
,您甚至可以按名称而不是按位置进行格式化,从而使代码更具可读性。
最后,高分文件本身就是一团乱七八糟的东西,因为pickle
它不适合人类消费。如果您希望它是人类可读的,您必须选择一种格式,并编写代码来序列化该格式。幸运的是,CSV 格式非常易于阅读,并且大部分代码已经在csv
模块中为您编写好了。(您可能想查看DictReader
和DictWriter
类,特别是如果您想编写标题行。同样,为了提高可读性,需要权衡更多代码。)