Python 如何将字典排序为仅从最高值输出?

Python 如何将字典排序为仅从最高值输出?,python,sorting,dictionary,Python,Sorting,Dictionary,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

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
函数,但是它只输出名称,而不输出分数本身,而且我希望输出的分数仅为最高,而不是像当前代码那样的先前分数。

我认为在这种情况下您不需要字典。只需将分数作为元组列表保存即可

即按名称排序:

>>> 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)]

您可以使用
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)
我会从一开始就使用来获得一个排序列表,每当你插入一个新分数时,那么这只是一个反转或获得所需输出的问题:

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]

然后,要获得所需的输出:

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

作为旁注
列表[:-1]
==反向列表,
列表[-1]
==最后一个元素

您的代码可以使用
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
key
参数按
d
中的值排序,而不是按其键排序

sorted(d, key=lambda x: max(d[x]))

把这一切放在一起,我们得到了

from collections import defaultdict
d = defaultdict(list)
with open('ClassA.txt') as f:
    for line in f:
        name, score = line.split(':')
        d[name.strip()].append(int(score.strip()))

# Original
print(sorted(d.items()))

# By score ascending
print(sorted(d.items(), key=lambda x: max(x[1])))

# By score descending
print(sorted(d.items(), key=lambda x: max(x[1]), reverse=True))

使用
itertools.groupby应该相当容易。让我做点什么up@user3809875不,您误解了这个问题。在这些情况下,您应该使用
操作符.itemgetter
,而不是编写自己的匿名函数