高分功能问题

时间:2013-10-15 18:32:46

标签: python

我正在尝试为课堂上的小琐事游戏创建一个高分列表。我有一个问题,因为我似乎无法得到打印输出不只是随机打印字典。这个片段实际上并不是来自完整的程序,因为我不想破坏任何东西,所以它只是试图推断出这个功能。

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等等。我很感激任何建议!谢谢!

7 个答案:

答案 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)

字典以任意顺序存储。如果要对输出进行排序,则必须手动执行此操作。由于您的密钥score1score2等恰好按正确顺序排序,因此您可以这样做:

for i in sorted(scores):
    print(scores[i]['initials'], "\t", scores[i]['score'])

但是,您的代码实际上似乎并没有正确地维护该字典;当您找到分数为score2的用户时,您只需将score2替换为新分数,而不是将其推至score3,依此类推。

而且我不确定你为什么要首先以这种方式存储乐谱。如果您想维护订单,为什么不在0而不是4list score1中使用score5dict的密钥}?例如:

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)