在python中,如何按元素的频率对列表进行排序

时间:2014-10-10 09:07:25

标签: python algorithm sorting itertools

我有一个元素列表:[ 3, 3, 6, 6, 6, 5, 5, 8 ],需要按元素的频率对其进行排序才能得到这个:几个元素的[ 6, 6, 6, 3, 3, 5, 5, 8 ]具有相同的频率按值排序。你能找到比这更简短的方法吗?

import collections
from operator import itemgetter, attrgetter

def freq_sort(arr):
    counter=collections.Counter(arr)
    com = sorted(counter.most_common(), key=itemgetter(1,0), reverse=True)
    com = map(lambda x: [x[0]] * x[1], com)
    return [item for sublist in com for item in sublist]

4 个答案:

答案 0 :(得分:6)

试试这个

>>> old_list = [ 3, 3, 6, 6, 6, 5, 5, 8 ]
new_list = sorted(old_list, key = old_list.count, reverse=True)
>>> new_list
[6, 6, 6, 3, 3, 5, 5, 8]

答案 1 :(得分:2)

collections.Counter方法most_common()几乎可以执行您想要的操作。它返回按频率排序的对(值,频率)。您还需要按列表对列表进行排序;该方法不保证它(规范说当频率相同时,值的顺序是任意的)。所以我们必须将它传递给sorted()函数。

以下是代码:

from collections import Counter

l = [ 3, 3, 6, 6, 6, 5, 5, 8 ]
c = Counter(l)
sc = sorted(c.most_common(), key=lambda x: (-x[1], x[0])) # sorting happens here
sl = [([v] * n) for (v, n) in sc]
ss = sum(sl, [])
print(ss)

这种方法优于其他方法,它只能在时间上运行O(m log m),其中m是l中的多个不同值。其他方法将在时间O(n log n)中运行,其中n是长度o l,其总是大于或等于不同值的数量。您基本上将使用Bucket Sort算法。

答案 2 :(得分:1)

这在行数方面稍微短一些,先按count计算,然后按值排序:

import collections
arr = [ 3, 3, 6, 6, 6, 5, 5, 8 ]
counter = collections.Counter(arr)
sorted( arr, key=lambda x: (counter[x], x), reverse=True )

答案 3 :(得分:0)

执行两种排序通常比lambda函数的额外开销更快。这是有效的,因为Python的排序是稳定的

>>> from collections import Counter
>>> L = [ 3, 3, 6, 6, 6, 5, 5, 8 ]
>>> c = Counter(L)
>>> sorted(sorted(L), key=c.get, reverse=True)
[6, 6, 6, 3, 3, 5, 5, 8]

第二种排序速度非常快,因为数据现在已经部分排序,其中蒂姆斯特擅长。