按频率和Python中的值对列表进行排序

时间:2018-03-26 16:25:02

标签: python list sorting

我有一个数字列表说,[2,2,3,3,4,1]我想按频率排序,如果频率计数(升序)相同,则按值排序(也按升序排序)。 Soln将是[1,4,2,2,3,3]

对于频率

from collections import Counter
print sorted(arr, key=Counter(arr).get)

但我不确定如何按相同频率计数元素的值进行排序

2 个答案:

答案 0 :(得分:3)

跟进@ bro-grammer的评论(我使用了元组的密钥,只调用了一次计数器):

这种方法首先必须通过列表进行计数,然后再进行一些排序。

from collections import Counter
def perseus_sort(l):
    counter = Counter(l)
    return sorted(l, key=lambda x: (counter[x], x))

可能有一些聪明的算法能够以某种方式结合这两者,但我的直觉是它会非常复杂并且超出你的需要

答案 1 :(得分:2)

这是通过numpy.uniquenumpy.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