我有一个名为marks的python
字典:
marks={’joe’:4, ’suzan’:5, ’peter’:4, ’bob’:4, ’john’:6, ’ann’:5, ’fred’:3}
我想根据他们在该测试中的排名来制作一份学生名单。更确切地说,建立一个列表排名,以便:
rank[0]
包含最佳学生列表rank[1]
包含第二好的学生名单等。输出应为:
[[’john’], [’ann’, ’suzan’], [’joe’, ’bob’, ’peter’], [’fred’]]
有人可以帮帮我吗?我尝试了一段时间,但我没有找到任何简单的解决方案..
感谢
答案 0 :(得分:2)
Python有一些很棒的内置库,比如itertools和operator。
下面是一个班轮:
from itertools import groupby
from operator import itemgetter
marks = {'ann': 5, 'bob': 4, 'fred': 3, 'joe': 4, 'john': 6, 'peter': 4, 'suzan': 5}
print [[name for name, rank in g] for k, g in groupby(sorted(marks.iteritems(), key=itemgetter(1), reverse=True), key=itemgetter(1))]
我的实施基于here示例。
答案 1 :(得分:1)
通用算法(伪代码)如下所示:
temp = {}
for student, rank in marks:
if not temp has key rank:
temp[rank] = []
push student to temp[rank]
keys = sort keys of temp
result = []
for key in keys:
push temp[key] to result
return result
更新:
Python实现:
marks={'joe':4, 'suzan':5, 'peter':4, 'bob':4, 'john':6, 'ann':5, 'fred':3}
temp = {}
for student in marks:
mark = marks[student]
if not temp.has_key(mark):
temp[mark] = []
temp[mark].append(student)
ranks = sorted([v for v in temp])
ranks.reverse()
result = []
for rank in ranks:
result.append(temp[rank])
print result
答案 2 :(得分:1)
使用defaultdict
的更具可读性的替代方案是
marks = {'ann': 5, 'bob': 4, 'fred': 3, 'joe': 4, 'john': 6, 'peter': 4, 'suzan': 5}
from collections import defaultdict
rankings = defaultdict(list)
for name,score in marks.iteritems():
rankings[score].append(name)
您知道rankings[6]
是最好的列表,即在这种情况下rankings[6]=[john]
。
要从此dict
恢复排名列表,您可以按键对项目进行排序:
result = []
for key in sorted(rankings,reverse=True):
result.append(rankings[key])
答案 3 :(得分:1)
一行
marks = {'ann': 5, 'bob': 4, 'fred': 3, 'joe': 4, 'john': 6, 'peter': 4, 'suzan': 5}
[[name for name, val in marks.items() if val == score]\
for score in sorted(set(marks.values()))]
编辑:为清晰起见更改了名称。
答案 4 :(得分:0)
我当然不知道你的用例,但似乎最好将信息存储在一个新的“倒置字典”中,而不是创建一个单独的学生列表列表而没有附加任何分数信息:
marks_inverted = {v: [] for v in marks.values()}
for k,v in marks.items():
marks_inverted[v].append(k)
print(marks_inverted)
#OUTPUT: {6: ['john'], 5: ['suzan', 'ann'], 4: ['bob', 'joe', 'peter'], 3: ['fred']}
#Note that as a dict, marks_inverted doesn't have any order
现在,您可以查看获得每个分数的学生列表:
print(marks_inverted[6])
#OUTPUT: ['john']
或最高分:
print(marks_inverted[max(marks_inverted)]
#OUTPUT: ['john']
如果您使用的是collections.defaultdict
而不是常规的dict
,那么如果您要求获得无人分数,您就不必担心会出错,而且您无需初始化首先是空列表(想法来自here):
from collections import defaultdict as dd
marks_inverted = dd(list)
for k,v in marks.items():
marks_inverted[v].append(k)
#if marks_inverted[v] doesn't exist it is initialized as [] before it is appended
现在,如果你向上看2,即使没有人得到2:
,也不会出现错误print(marks_inverted[2])
#OUTPUT: []
如果你正在使用collections.defaultdict
,并且想要获得超过一系列分数的学生,你可以这样做:
[marks_inverted[k] for k in range(2,5) if marks_inverted[k]]
#OUTPUT: [['fred'], ['bob', 'joe', 'peter']]
...或者如果您希望列表展平:
[name for index in [marks_inverted[k] for k in range(2,5) if marks_inverted[k]] for name in index]
#OUTPUT: ['fred', 'bob', 'joe', 'peter']
(语句的if marks_inverted[k]
部分使得没有空列表作为列表输出的成员包含在内。)
如果您在任何时候确实需要删除分数信息并且只有最高分到最低分的学生列表(如原始问题中所示),您可以这样做:
[marks_inverted[k] for k in reversed(sorted(marks_inverted)) if marks_inverted[k]]
#OUTPUT: [['john'], ['ann', 'suzan'], ['bob', 'joe', 'peter'], ['fred']]