我有一个元素列表:[ 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]
答案 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]
第二种排序速度非常快,因为数据现在已经部分排序,其中蒂姆斯特擅长。