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

Python中按频率和值对列表排序,python,list,sorting,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) 但我不知道如何按相同频率计数元素的值排序为了跟进@brogrammer的评论,我使用了一个元组作为键,只调用了一次计数器: 有一种方法,它首先要通过列表进行计数,然后再进行一些排序 from co

我有一个数字列表,上面写着,[2,2,3,3,4,1]我想按频率排序,如果频率计数升序相同,那么也按值升序排序。Soln将是[1,4,2,2,3,3]

频率

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

但我不知道如何按相同频率计数元素的值排序

为了跟进@brogrammer的评论,我使用了一个元组作为键,只调用了一次计数器:

有一种方法,它首先要通过列表进行计数,然后再进行一些排序

from collections import Counter
def perseus_sort(l):
    counter = Counter(l)
    return sorted(l, key=lambda x: (counter[x], x))
可能有一些聪明的算法可以以某种方式将这两者结合起来,但我的直觉是,这将非常复杂,超出您的需要

这是通过numpy.unique和numpy.lexsort实现的一种方法:

以下是针对大型阵列的一些基准测试:

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

查看Python排序教程,了解如何使用辅助键。跨语言的一种常见方式是先按辅助键排序,然后按主键排序,使用大多数语言提供的稳定排序。sortedl,key=lambda x:[l.countx,x]@bro grammar对于大型列表,这将非常缓慢,因为它必须为每个item@Omer是的,我同意。可能更好的方法是使用计数器构建频率dict。我只是想向OP展示如何使用多个键进行排序。我喜欢@Prune的想法。首先按值排序,然后按频率排序。从集合导入计数器def custom_sortl:l=sortedl返回sortedl,key=Counter l.get
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