0

我正在编写一个高分系统,用户将输入一个名称和一个分数,然后程序将测试分数是否大于 high_scores 中的最低分数。如果是,将写入分数并删除最低分数。一切正常,但我注意到了一些事情。high_scores.txt文件是这样的:

PL1 50
PL2 50
PL3 50
PL4 50
PL5 50

PL1 是添加的第一个分数,PL2 是第二个,PL3 是第三个,依此类推。然后我尝试添加另一个分数,高于所有其他分数(PL6 60),结果是程序将 PL1 指定为最低分数。添加了 PL6,删除了 PL1。这正是我想要的行为,但我不明白它是如何发生的。字典是否跟踪分配项目的时间点?这是代码:

MAX_NUM_SCORES = 5

def getHighScores(scores_file):
    """Read scores from a file into a list."""

    try:
        cache_file = open(scores_file, 'r')
    except (IOError, EOFError):
        print("File is empty or does not exist.")
        return []
    else:
        lines = cache_file.readlines()
        high_scores = {}

        for line in lines:
            if len(high_scores) < MAX_NUM_SCORES:
                name, score = line.split()
                high_scores[name] = int(score)
            else:
                break

        return high_scores

def writeScore(file_, name, new_score):
    """Write score to a file."""

    if len(name) > 3:
        name = name[0:3]

    high_scores = getHighScores(file_)

    if high_scores:
        lowest_score = min(high_scores, key=high_scores.get)
        if new_score > high_scores[lowest_score] or len(high_scores) < 5:
            if len(high_scores) == 5:
                del high_scores[lowest_score]

            high_scores[name.upper()] = int(new_score)                  
        else:
            return 0
    else:
        high_scores[name.upper()] = int(new_score)

    write_file = open(file_, 'w')
    while high_scores:
        highest_key = max(high_scores, key=high_scores.get)
        line = highest_key + ' ' + str(high_scores[highest_key]) + '\n'
        write_file.write(line)
        del high_scores[highest_key]

    return 1

def displayScores(file_):
    """Display scores from file."""

    high_scores = getHighScores(file_)

    print("HIGH SCORES")
    if high_scores:
        while high_scores:
            highest_key = max(high_scores, key=high_scores.get)
            print(highest_key, high_scores[highest_key])
            del high_scores[highest_key]
    else:
        print("No scores yet.")

def resetScores(file_):
    open(file_, "w").close()
4

3 回答 3

1

正如其他人指出的那样,字典中项目的顺序是“由实施决定的”。

这个答案更多地是对您的问题的评论,“如何min()决定什么分数是最低的?”,但是对于评论来说太长而且格式太长了。:-)

有趣的是两者都max可以min这样使用。原因是他们(可以)处理“可迭代”,并且字典是可迭代的:

for i in some_dict:

循环i遍历字典中的所有键。在您的情况下,键是用户名。此外,minmax允许传递key参数以将迭代中的每个候选者转换为适合二进制比较的值。因此,min它几乎等同于以下 python 代码,其中包括一些跟踪以准确显示其工作原理:

def like_min(iterable, key=None):
    it = iter(iterable)
    result = it.next()
    if key is None:
        min_val = result
    else:
        min_val = key(result)
    print '** initially, result is', result, 'with min_val =', min_val
    for candidate in it:
        if key is None:
            cmp_val = candidate
        else:
            cmp_val = key(candidate)
        print '** new candidate:', candidate, 'with val =', cmp_val
        if cmp_val < min_val:
            print '** taking new candidate'
            result = candidate
    return result

如果我们在示例字典上运行上述内容d,则使用d.get我们的key

d = {'p': 0, 'ayyy': 3, 'b': 5, 'elephant': -17}
m = like_min(d, key=d.get)
print 'like_min:', m

** initially, result is ayyy with min_val = 3
** new candidate: p with val = 0
** taking new candidate
** new candidate: b with val = 5
** new candidate: elephant with val = -17
** taking new candidate
like_min: elephant

我们发现我们得到了值最小的键。当然,如果多个值相等,“最小”的选择取决于字典迭代顺序(以及是min实际使用<还是<=内部使用)。

(此外,您用来“排序”高分以打印出来的方法是 O(n 2 ):选择最高值,将其从字典中删除,重复直到为空。这会遍历 n 个项目,然后是 n-1,.. . then 2, then 1 => n+(n-1)+...+2+1 steps = n(n+1)/2 = O(n 2 ). 删除高的也是一个昂贵的操作,虽然我认为它仍然应该在 O(n 2 ) 或以下。在 n=5 的情况下,这还不错(5 * 6 / 2 = 15),但是......不优雅。:-))

于 2013-07-27T00:24:29.087 回答
1

不。你得到的结果是由于dict实现内部的任意选择,你不能依赖于总是发生。(虽然有一个子类dict确实跟踪插入顺序:collections.OrderedDict。)我相信在当前的实现中,如果您切换 PL1 和 PL2 行的顺序,PL1 可能仍会被删除。

于 2013-07-26T23:20:54.353 回答
0

这几乎就是http://stromberg.dnsalias.org/~strombrg/python-tree-and-heap-comparison/的内容。

简短版:获取treap 模块,它的工作方式类似于排序字典,并保持键的顺序。或者使用 nest 模块自动获取 n 个最大(或最小)值。

collections.OrderedDict 有利于保留插入顺序,但不能保留键顺序。

于 2013-07-27T00:23:26.820 回答