使用Python对字典进行排序,以“值”作为主键,“键”作为次要键。

3
我在这里尝试的是按照字符在字符串中出现的次数逆序显示字符。如果两个字符具有相同的出现次数,则应按字母顺序显示它们。
因此,给定一个字符串 'abaddbccdd',我想要的输出是: ['d', 'a', 'b', 'c']
以下是我目前所做的:
>>> from collections import Counter
>>> s = 'abaddbccdd'
>>> b = Counter(s)
>>> b
Counter({'d': 4, 'a': 2, 'c': 2, 'b': 2})
>>> b.keys()
['a', 'c', 'b', 'd']
>>> c = sorted(b, key=b.get, reverse=True)
>>> c
['d', 'a', 'c', 'b']
>>>

如何处理第二部分?'a'、'b'和'c'在文本中都恰好出现两次,且顺序不正确。最好的方法(希望是最短的方法)是什么?

4个回答

3

这可以通过单次排序完成。诀窍是使用计数数字的负值作为主要排序键,字典键字符串作为次要排序键进行升序排序。

b = {'d': 4, 'a': 2, 'c': 2, 'b': 2}
c = sorted(b, key=lambda k:(-b[k], k))
print(c)

输出

['d', 'a', 'b', 'c']

2
最简单的方法是:
>>> sorted(sorted(b), key=b.get, reverse=True)
['d', 'a', 'b', 'c']

所以先按照自然顺序(键顺序)对序列进行一次排序,然后按值进行反向排序。
注意,如果字典很大,这种方法的运行时间可能不是最快的,因为它执行了两次完整的排序,但实际上这可能是最简单的方法,因为您想让值降序而键升序。
它有效的原因在于Python保证排序是稳定的。这意味着当键相等时,原始顺序将被保留,因此如果您从最后一个键重复排序到第一个键,您将获得所需的结果。此外,`reverse=True`不同于仅翻转输出,因为它还尊重稳定性,并仅在键不同时才翻转结果。

1
您可以使用一个lambda函数:
>>> sorted(b, key=lambda char: (b.get(char), 1-ord(char)), reverse=True)

该关键函数在OP的数据中返回['a', 'b', 'c', 'd'],而不是所期望的['d', 'a', 'b', 'c'] - PM 2Ring
@PM2Ring:很抱歉。现在我已经编辑过了,但我不确定这是否是一个好答案。 - zondo
你可以直接使用-ord(char)。你的解决方案适用于OP的目的,但当dict键不是单个字符时,它当然无法工作。当dict值为非数字时,我的版本当然也无法工作,尽管如果保证dict是计数器,则这不是问题。 - PM 2Ring

1
如果您已经在使用计数器对象,那么可以使用Counter.most_common方法。它将按照频率从高到低的顺序返回项目列表。
>>> b.most_common()
[('d', 4), ('a', 2), ('b', 2), ('c', 2)]

1
我刚刚检查了一下,如果字符具有相同的频率,它并不总是按正确的字母顺序返回(例如先是'a',然后是'b',然后是'c')。因此,为确保正确性,我仍需要对其进行排序。 - akash12300

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接