按出现频率对列表进行排序

22 投票
7 回答
42119 浏览
提问于 2025-04-18 05:08

我有一个整数(或者也可以是字符串)的列表,我想按照它们出现的频率来排序,举个例子:

a = [1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]

在这个例子中,元素 5 在列表中出现了 4 次,而 4 出现了 3 次。所以排序后的输出列表应该是:

result = [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

我试过用 a.count(),但这个方法只是告诉我某个元素出现了多少次。我想要的是排序。有没有什么好主意?

谢谢

7 个回答

0

这不是个有趣的方法...

a = [1,1,2,3,3,3,4,4,4,5,5,5,5]

from collections import Counter
result = []
for v, times in sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True):
    result += [v] * times

一句话搞定:

reduce(lambda a, b: a + [b[0]] * b[1], sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True), [])
1

如果你已经在使用numpy,或者可以选择使用它,这里还有一个其他的选择:

In [309]: import numpy as np

In [310]: a = [1, 2, 3, 3, 1, 3, 5, 4, 4, 4, 5, 5, 5]

In [311]: vals, counts = np.unique(a, return_counts=True)

In [312]: order = np.argsort(counts)[::-1]

In [313]: np.repeat(vals[order], counts[order])
Out[313]: array([5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2])

这个结果是一个numpy数组。如果你想得到一个Python列表,可以调用这个数组的 tolist() 方法:

In [314]: np.repeat(vals[order], counts[order]).tolist()
Out[314]: [5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2]
3
In [15]: a = [1,1,2,3,3,3,4,4,4,5,5,5,5]

In [16]: counts = collections.Counter(a)

In [17]: list(itertools.chain.from_iterable([[k for _ in range(counts[k])] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
Out[17]: [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

另外:

answer = []
for k in sorted(counts, key=counts.__getitem__, reverse=True):
    answer.extend([k for _ in range(counts[k])])

当然,[k for _ in range(counts[k])] 可以用 [k]*counts[k] 来替代。
所以第17行变成了

list(itertools.chain.from_iterable([[k]*counts[k] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
10

使用Python 3.3和内置的 sorted 函数,并把计数作为排序的依据:

>>> a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
>>> sorted(a,key=a.count)
[2, 1, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
>>> sorted(a,key=a.count,reverse=True)
[5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
42
from collections import Counter
print [item for items, c in Counter(a).most_common() for item in [items] * c]
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

或者更好(更高效)的实现方式

from collections import Counter
from itertools import repeat, chain
print list(chain.from_iterable(repeat(i, c) for i,c in Counter(a).most_common()))
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

或者

from collections import Counter
print sorted(a, key=Counter(a).get, reverse=True)
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

如果你更喜欢原地排序

a.sort(key=Counter(a).get, reverse=True)

撰写回答