【问题标题】:In python, how to sort list by frequency of elements在python中,如何按元素的频率对列表进行排序
【发布时间】:2014-10-10 09:07:24
【问题描述】:

我有一个元素列表:[ 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]

【问题讨论】:

  • 属于 codereview.stackexchance。
  • 定义“更短”。 Darth Kotik 提出的答案在字符方面更短,但它不必要地为列表中的每个唯一元素执行一个额外的循环。附带说明一下,如果在具有可变元素的列表中使用给定的解决方案,则会产生问题。

标签: python algorithm sorting itertools


【解决方案1】:

试试这个

>>> 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]

【讨论】:

  • 当计数相等时,这不会按值排序。也有 list.count 作为关键功能不是很有效(使排序 O(N*N))
  • 您能否进行一些基准测试以显示执行时间与相关解决方案的比较?
  • 如果old_list 的长度足够,你会想记住old_list.count
【解决方案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,它总是大于或等于不同值的数量。您基本上将使用桶排序算法。

【讨论】:

    【解决方案3】:

    这在行数方面有点短,首先按计数排序,然后按值排序:

    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 )
    

    【讨论】:

    • 应该是(counter[x], -x)才能得到正确的顺序
    【解决方案4】:

    执行两种排序通常比 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]
    

    第二次排序非常快,因为数据现在已经部分排序,这是 timsort 擅长的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 2015-10-18
      • 2020-10-19
      相关资源
      最近更新 更多