txt会包含以下内容:
Matt Scored: 10
Jimmy Scored: 3
James Scored: 9
Jimmy Scored: 8
....
到目前为止我的代码:
from collections import OrderedDict
#opens the class file in order to create a dictionary
dictionary = {}
#splits the data so the name is the key while the score is the value
f = open('ClassA.txt', 'r')
d = {}
for line in f:
firstpart, secondpart = line.strip().split(':')
dictionary[firstpart.strip()] = secondpart.strip()
columns = line.split(": ")
letters = columns[0]
numbers = columns[1].strip()
if d.get(letters):
d[letters].append(numbers)
else:
d[letters] = list(numbers)
#sorts the dictionary so it has a alphabetical order
sorted_dict = OrderedDict(
sorted((key, list(sorted(vals, reverse=True)))
for key, vals in d.items()))
print (sorted_dict)
此代码已生成按字母顺序排序的名称输出,其分数从最高到最低打印。但是现在我需要能够输出以最高得分为第一,最低得分为最后得分的名称。我尝试使用max
函数,但它只输出名称而不是分数本身,我也希望输出的分数最高,而不是之前的分数,就像我当前的代码一样。
答案 0 :(得分:1)
在这种情况下,我认为你不需要字典。只需将分数作为元组列表。
即。按名称排序:
>>> sorted([('c', 10), ('b', 16), ('a', 5)],
key = lambda row: row[0])
[('a', 5), ('b', 16), ('c', 10)]
或者得分:
>>> sorted([('c', 10), ('b', 16), ('a', 5)],
key = lambda row: row[1])
[('a', 5), ('c', 10), ('b', 16)]
答案 1 :(得分:0)
您可以使用itertools.groupby
自行分隔每个密钥。那个很长的dict comp很难看,但它主要是通过对输入进行排序,将它按冒号前的部分分组,然后取出最大的结果并用组名保存它。
import itertools, operator
text = """Matt Scored: 10
Jimmy Scored: 3
James Scored: 9
Jimmy Scored: 8"""
result_dict = {group:max(map(lambda s: int(s.split(":")[1]), vals)) for
group,vals in itertools.groupby(sorted(text.splitlines()),
lambda s: s.split(":")[0])}
sorted_dict = sorted(result_dict.items(), key=operator.itemgetter(1), reverse=True)
# result:
[('Matt Scored', 10), ('James Scored', 9), ('Jimmy Scored', 8)]
展开dict comp会产生类似的结果:
sorted_txt = sorted(text.splitlines())
groups = itertools.groupby(sorted_txt, lambda s: s.split(":")[0])
result_dict = {}
for group, values in groups:
# group is the first half of the line
result_dict[group] = -1
# some arbitrary small number
for value in values:
#value is the whole line, so....
value = value.split(":")[1]
value = int(value)
result_dict[group] = max(result_dict[group], value)
答案 2 :(得分:0)
我会从一开始就使用 bisect.insort ,每当你插入一个新的分数时都会有一个排序列表,那么只需要反转或slicing the list来获得期望的输出:
from bisect import insort
from StringIO import StringIO
d = {}
f = '''Matt Scored: 10
Jimmy Scored: 3
James Scored: 9
Jimmy Scored: 8'''
for line in StringIO(f):
line = line.strip().split(' Scored: ')
name, score = line[0], int(line[1])
if d.get(name):
# whenever new score is inserted, it's sorted from low > high
insort(d[name], score)
else:
d[name] = [score]
d
{'James': [9], 'Jimmy': [3, 8], 'Matt': [10]}
然后获得所需的输出:
for k in sorted(d.keys()):
# score from largest to smallest, sorted by names
print 'sorted name, high>low score ', k, d[k][::-1]
# highest score, sorted by name
print 'sorted name, highest score ', k, d[k][-1]
结果:
sorted name, high>low score James [9]
sorted name, highest score James 9
sorted name, high>low score Jimmy [8, 3]
sorted name, highest score Jimmy 8
sorted name, high>low score Matt [10]
sorted name, highest score Matt 10
作为旁注:list[::-1]
==反向列表,list[-1]
==最后一个元素
答案 3 :(得分:0)
使用defaultdict
from collections import defaultdict
d = defaultdict(list)
接下来,在处理文件时使用open
上下文管理器是一种很好的做法。
with open('ClassA.txt') as f:
最后,当循环遍历f
的行时,您应该使用单个字典,而不是两个字典。要更轻松地按分数排序,您需要将分数存储为int
。
for line in f:
name, score = line.split(':')
d[name.strip()].append(int(score.strip()))
此方法的一个副作用是,在创建新列表时,具有多个数字的分数(例如Jimmy Scored: 10
)将保持其值(10
)。在原始版本中,list('10')
会生成list['1', '0']
。
您可以使用sorted
的{{1}}参数按key
中的值而不是其键进行排序。
d
把它们放在一起我们得到了
sorted(d, key=lambda x: max(d[x]))