我正在尝试为课堂上的小琐事游戏创建一个高分列表。我有一个问题,因为我似乎无法得到打印输出不只是随机打印字典。这个片段实际上并不是来自完整的程序,因为我不想破坏任何东西,所以它只是试图推断出这个功能。
scores = {'score1': {'initials': 'ywo',
'score': 20},
'score2': {'initials': 'JRV',
'score': 18},
'score3': {'initials': 'blh',
'score': 16},
'score4': {'initials': 'yth',
'score': 15},
'score5': {'initials': 'rtg',
'score': 12}}
total_score = 17
#iterates over the scores to see if new score and initials should be input
for i in (scores):
if total_score > scores[i]['score']:
scores[i]['initials'] = 'JKE'
scores[i]['score'] = total_score
break
#prints scores in a table like format rather than list
print("HIGH\tSCORES")
for i in scores:
print(scores[i]['initials'], "\t", scores[i]['score'])
我的输出每次都是随机的。我只是希望字典按从高到低的顺序打印,例如:
ywo 20
JRV 18
JKE 17
等等
我遇到的另一个问题是,我不确定如何在字典中将其他分数降低。因此,如果JKE的分数取代了blh的分数,blh不仅会从字典中删除,而且会向下移动到score4 index,score4的值会移动到score5等等。我很感激任何建议!谢谢!
答案 0 :(得分:1)
我认为你可能会试图让它有点过于复杂(虽然听起来像是家庭作业所以这可能是一个要求)。
我会像这样接近它:
scores = {'YWO': 20,
'BLH': 16,
'YTH': 15,
'JRV': 18,
'RTG': 12,
}
def display_scores(scores):
for score, name in sorted(((scores[k], k) for k in scores, reverse=True):
print(name, score)
然后您可以通过以下方式轻松添加玩家和分数:
scores[initials] = scores.get(initials, 0) + 1 #or points or whatever
答案 1 :(得分:0)
如果您使用OrderedDict,词典不会保留任何特定的顺序。
from collections import OrderedDict
d = OrderedDict([('first', 1),('second', 2),('third', 3)])
print d.items()
输出:
[('first', 1), ('second', 2), ('third', 3)]
答案 2 :(得分:0)
字典以任意顺序存储。如果要对输出进行排序,则必须手动执行此操作。由于您的密钥score1
,score2
等恰好按正确顺序排序,因此您可以这样做:
for i in sorted(scores):
print(scores[i]['initials'], "\t", scores[i]['score'])
但是,您的代码实际上似乎并没有正确地维护该字典;当您找到分数为score2
的用户时,您只需将score2
替换为新分数,而不是将其推至score3
,依此类推。
而且我不确定你为什么要首先以这种方式存储乐谱。如果您想维护订单,为什么不在0
而不是4
到list
score1
中使用score5
到dict
的密钥}?例如:
scores = [{'initials': 'ywo',
'score': 20},
{'initials': 'JRV',
'score': 18},
{'initials': 'blh',
'score': 16},
{'initials': 'yth',
'score': 15},
{'initials': 'rtg',
'score': 12}]
for i, score in enumerate(scores):
if total_score > score['score']:
scores[i:i+1] = {'initials': 'JKE', 'score': total_score}
del scores[5:]
break
现在,它们始终按顺序排列:
for score in scores:
print(score['initials'], "\t", score['score'])
使用heapq
可以提高效率。但是,这有点复杂,因为heapq
通过比较值本身来保持其值排序,但您希望它在value['score']
上进行比较。与Python中大多数与排序相关的功能不同,heapq
没有key
功能来简化这一过程。所以,你必须做一些手工“装饰 - 排序 - 不合理”的工作:
decorated_scores = [(score['score'], score) for score in scores]
heapify(decorated_scores)
现在,要添加新的高分:
new_score = (total_score, {'initials': 'JRV', 'score': total_score})
dropped_off = heappushpop(decorated_scores, new_score)
if dropped_off == new_score:
# didn't make the high scores
else:
# did
另一种简化方法是使用自动排序列表,例如bisect
文档中引用的SortedCollection
配方或blist.sortedlist
等库。
答案 3 :(得分:0)
字典是一种非排序类型,因此每次都期望订单每次都会改变是合理的。
我认为你应该考虑不同的数据类型来处理这个问题(这也回答你问题的第二部分)。
我认为你应该考虑有序字典 - http://docs.python.org/2/library/collections.html
或者我认为更适合此目的的东西 - http://docs.python.org/2/library/heapq.html
答案 4 :(得分:0)
你需要以某种方式保持你的分数。最好的方法是保留一个有序列表。您可以使用bisect
模块来帮助您执行此操作。 bisect.bisect(list, item)
返回应将item
插入列表的索引,以便列表仍然排序。如果我们将得分保持为(score, name)
元组的列表,则默认元组比较将起作用 - 较小的分数将是第一个,较高的分数最后。我们每次都可以删除除最后五个元素之外的所有元素,只保留前五个分数。
def add_score(scores, name, score):
new_item = (score, name)
scores.insert(bisect.bisect(scores, new_item), new_item)
del scores[:-5] #keep only the top 5 scores
要打印它们,我们将列表反转:
def print_scores(scores):
for score, name in reversed(scores):
print "%s\t%s" % (name, score)
用法:
>>> scores = []
>>> add_score(scores, "fool", 10)
>>> scores
[(10, 'fool')]
>>> add_score(scores, "jimbo", 100)
>>> scores
[(10, 'fool'), (100, 'jimbo')]
>>> add_score(scores, "bob", 20)
>>> scores
[(10, 'fool'), (20, 'bob'), (100, 'jimbo')]
>>> add_score(scores, "ha", 3)
>>> scores
[(3, 'ha'), (10, 'fool'), (20, 'bob'), (100, 'jimbo')]
>>> add_score(scores, "bob", 200)
>>> add_score(scores, "bob", 140)
>>> add_score(scores, "bob", 50)
>>> scores
[(20, 'bob'), (50, 'bob'), (100, 'jimbo'), (140, 'bob'), (200, 'bob')]
>>> print_scores(scores)
bob 200
bob 140
jimbo 100
bob 50
bob 20
答案 5 :(得分:0)
我会使用词典列表,然后您可以轻松地对分数进行排序,例如只显示最佳3。 列表的格式可以是: [{分数:玩家},...]
答案 6 :(得分:0)
我认为可能有比你拥有的更好的数据结构,我只进行了一次调整,使你的键到字典整数,这将解决你的打印问题,该功能将建立一个新的排行榜,将最多5个条目,并将新分数放在它所属的位置。如果出现平局,提交的第二个分数将转到输入的较低位置。分数必须超过最低分才能成为董事会成员。
scores = {1: {'initials': 'ywo',
'score': 20},
2: {'initials': 'JRV',
'score': 18},
3: {'initials': 'blh',
'score': 16},
4: {'initials': 'yth',
'score': 15},
5: {'initials': 'rtg',
'score': 12}}
def new_leaderboard(new_score,new_initials):
going_down_a_place = []
place_found = False
existing_scores = scores.copy()
for i in scores:
if new_score > scores[i]['score'] and place_found == False:
leaderboard_placement = i
place_found = True
if new_score > scores[i]['score']:
going_down_a_place.append(i)
if len(going_down_a_place) > 0:
going_down_a_place.remove(max(going_down_a_place))
for val in going_down_a_place:
place = val + 1
scores[place] = {'initials':existing_scores[val]['initials'],'score':existing_scores[val]['score']}
if place_found == True:
scores[leaderboard_placement] = {'initials':new_initials,'score':new_score}
for i in scores:
print(scores[i]['initials'], "\t", scores[i]['score'])
new_score = 21
new_initials = 'ddd'
new_leaderboard(new_score,new_initials)