我有一个数字列表说,[2,2,3,3,4,1]我想按频率排序,如果频率计数(升序)相同,则按值排序(也按升序排序)。索恩将是[1,4,2,2,3,3]
对于频率
from collections import Counter
print sorted(arr, key=Counter(arr).get)
但我不确定如何按相同频率计数元素的值排序
跟进@ bro-grammer的评论(我使用了元组的密钥,只调用了一次Counter):
有这种方法首先必须通过列表进行计数,然后再进行一些排序。
from collections import Counter
def perseus_sort(l):
counter = Counter(l)
return sorted(l, key=lambda x: (counter[x], x))
可能有一些聪明的算法可以以某种方式结合这两者,但我的直觉是它会非常复杂并且超出你的需要
这是通过numpy.unique
和numpy.lexsort
的一种方式:
import numpy as np
arr = np.array([2,2,3,3,4,1])
c = dict(zip(*np.unique(arr, return_counts=True)))
res = arr[np.lexsort((arr, list(map(c.get, arr))))]
# array([1, 4, 2, 2, 3, 3])
以下针对大型阵列的一些基准测试:
from collections import Counter
import numpy as np
arr = np.random.randint(0, 9, 100000)
def jp(arr):
c = dict(zip(*np.unique(arr, return_counts=True)))
res = arr[np.lexsort((arr, list(map(c.get, arr))))]
return res
def perseus_sort(l):
counter = Counter(l)
return sorted(l, key=lambda x: (counter[x], x))
%timeit jp(arr) # 39.2 ms
%timeit perseus_sort(arr) # 118 ms