在python中按字母顺序对字典中的数据进行排序

时间:2015-04-18 10:36:34

标签: python dictionary

我正在学习如何使用字典将名称和分数组合在一起。它打印出从高到低的分数。我试图让它只打印出每人最高分,我相信使用MAX,但我不能这样做。有什么想法吗?

我还需要计算每个学生的平均分数,所以如果他们有3个分数是使用len

scores = {}
resultfile = open("results.txt")
for line in resultfile:
    (name, score) = line.split()
    scores[score]=name
resultfile.close()

print("The top scores were:")
for each_score in sorted(scores.keys(), reverse = True):
     print(scores[each_score] + each_score)

3 个答案:

答案 0 :(得分:2)

您需要确保在此处使用正确的数据类型;对要从str转换为int的分数(整数)进行排序;字符串按字典顺序排序(首先是字符,然后是第二个字符,就像字母表一样),整数在数字上进行比较。因此字符串'10''9'之前排序,但整数109之后排序。

您还需要在每个名称的列表中存储您的分数,而不仅仅是存储姓氏和分数:

scores = {}
resultfile = open("results.txt")
for line in resultfile:
    name, score = line.split()
    score = int(score)
    scores.setdefault(name, []).append(score)
resultfile.close()

现在您有name - >的映射[score1, score2, score3, ...]

你需要在这里写一个排序键;一个返回字典中给定键的最大分数:

sorted(scores, key=lambda key: max(scores[key]), reverse=True)

key函数的sorted()参数必须是一个函数,并且为每个依次排序的元素赋予它,并且应该返回要排序的值。如果scores[key]是该给定用户的所有分数,那么max(scores[key])将是他们的最高分。

如果您的分数已经从最高分到最低分,那么您不需要关键功能,因为序列会按字典顺序进行比较。

接下来,如果您需要显示最高分,那么您需要max()

sorted_by_highest_score = sorted(scores, key=lambda key: max(scores[key]), reverse=True)
for name in sorted_by_highest_score:
    highest_score = max(scores[name])
    print(name, highest_score)

要计算平均值,您需要做的就是将得分之和除以得分数,所以使用len()

average = sum(scores[name]) / len(scores[name])

答案 1 :(得分:0)

您的主要问题是您已将分数映射到名称:

scores[score]=name

如果两个人得分相同怎么办? score[score] = name会覆盖(丢失)其中一个名称,因为dict只能将一个密钥(例如得分)改为一个值(例如名称)。因此,您需要将名称映射到分数列表:

scores.setdefault(name, []).append(name)
如果scores[name]位于name,则

The setdefault method会返回scores,并返回分配给[]的新空列表scores[name],否则为scores


<强>排序

sorted(scores)作为dict将名称映射到分数,从字面上对名称进行排序很容易:您可以使用scores

要按照从最高到最低的最高分数对sorted(scores, key=lambda name: max(scores[name]), reverse=True) 进行排序,您可以使用

key

有关排序的优秀教程,请参阅HOWTO Sort,包括使用In [100]: d = collections.deque(maxlen=3) 参数。


保留最后三个值

要仅存储每个名称的最后三个值,您可以使用collections.deque,这是一个类似列表的容器,可以具有最大长度。当项目附加到双端队列时,如果已达到最大长度,则会删除旧项目。

例如,这是一个最大长度为3的双端队列:

In [101]: d.extend([1,2,3])

In [102]: d
Out[102]: deque([1, 2, 3], maxlen=3)

我们可以插入三个值:

In [103]: d.append(4)

In [104]: d
Out[104]: deque([2, 3, 4], maxlen=3)

但是当我们插入第四个值时,只保留最后三个值:

import collections

scores = {}
with open("results.txt") as resultfile:
    for line in resultfile:
        name, score = line.split()
        scores.setdefault(name, collections.deque(maxlen=3)).append(float(score))

print("The top and average scores were:")
for name in sorted(scores, key=lambda name: max(scores[name]), reverse=True):
    ave = sum(scores[name])/len(scores[name])
    m = max(scores[name])
    print('{name}: {m} {a}'.format(name=name, m=m, a=ave))

因此,要根据每人最后3个分数的最大值对名称进行排序, 你可以使用:

max(scores[name])

避免双重计算的替代方法

上述代码的一个缺点是数量sorted计算两次:一次调用for-loop,一次调入data

避免这种双重计算的一种方法是预先计算一次值并将结果存储在列表data = [] for name, vals in scores.items(): m = max(vals) ave = sum(vals)/len(vals) data.append((ave, name, m)) 中:

data

(ave, name, m)现在是元组列表。每个元组的格式为for ave, name, m in sorted(data, reverse=True): print('{name}: {m} {a}'.format(name=name, m=m, a=ave)) 。 按字典顺序对元组列表进行排序。元组根据第一个元素排序,第二个元素用于断开关系,然后第三个元素用于打破任何剩余的关系,依此类推。

所以

data

将迭代data中的元组,从最高平均值到最低平均值,并且平均值仅计算一次。这样做的缺点是需要更多内存(存储{{1}})。所以上面显示的两个选项各有一个pro和con。第一种方法需要较少的内存,第二种方法需要较少的计算。

答案 2 :(得分:0)

我从您编写的代码中看到的潜在问题是删除具有相同分数的学生的潜力。根据您在此处撰写的代码:

(name, score) = line.split()
scores[score]=name

相反,如果要检查得分[得分]是否为空,那么您基本上会替换过去的名称。我不知道结果是什么样的,所以看起来所有学生都有独特的分数。

现在回答你的问题:

  

我试图让它只打印出每人最高分   我认为它使用的是MAX,但我无法做到。 [你为什么问?]

您希望打印出存储在词典中的每个人的最高分数,但是如何存储数据并不会使这一点变得简单。

我建议您将名称作为键并将分数存储为值,然后在迭代字典时,您可以自由使用Max获得最高分。

至于平均值,我建议你按照我上面写的建议。

我希望这会有所帮助。