【问题标题】:Sorting a List by frequency of occurrence in a list按列表中出现的频率对列表进行排序
【发布时间】:2014-06-19 05:08:00
【问题描述】:

我有一个整数列表(甚至可以是字符串),我想按 Python 中出现的频率对其进行排序,例如:

a = [1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]

这里元素5在列表中出现了4次,4出现了3次。所以输出排序列表将是:

result = [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

我尝试使用a.count(),但它给出了元素的出现次数。 我想对其进行排序。知道怎么做吗?

谢谢

【问题讨论】:

  • 输出中43的顺序是否重要?
  • 不,真的没关系,如果它让它更简单
  • 酷,否则我必须重新排序:-)

标签: python list sorting


【解决方案1】:
from collections import Counter
print [item for items, c in Counter(a).most_common() for item in [items] * c]
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

甚至更好(高效)的实现

from collections import Counter
from itertools import repeat, chain
print list(chain.from_iterable(repeat(i, c) for i,c in Counter(a).most_common()))
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

或者

from collections import Counter
print sorted(a, key=Counter(a).get, reverse=True)
# [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]

如果您更喜欢就地排序

a.sort(key=Counter(a).get, reverse=True)

【讨论】:

    【解决方案2】:

    使用Python 3.3和内置的sorted函数,以count为key:

    >>> a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
    >>> sorted(a,key=a.count)
    [2, 1, 1, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5]
    >>> sorted(a,key=a.count,reverse=True)
    [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
    

    【讨论】:

    • list.count 我相信它会变得非常低效。
    • @thefourtheye 我必须确定时间才能确定,但​​这听起来不错。诚然,这对于像示例这样的小列表来说是非常安全的。
    【解决方案3】:
    In [15]: a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
    
    In [16]: counts = collections.Counter(a)
    
    In [17]: list(itertools.chain.from_iterable([[k for _ in range(counts[k])] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
    Out[17]: [5, 5, 5, 5, 3, 3, 3, 4, 4, 4, 1, 1, 2]
    

    或者:

    answer = []
    for k in sorted(counts, key=counts.__getitem__, reverse=True):
        answer.extend([k for _ in range(counts[k])])
    

    当然,[k for _ in range(counts[k])] 可以替换为[k]*counts[k]
    所以第 17 行变成了

    list(itertools.chain.from_iterable([[k]*counts[k] for k in sorted(counts, key=counts.__getitem__, reverse=True)]))
    

    【讨论】:

    • @Aशwiniचhaudhary:我考虑过,但如果元素不是原始类型,它可能不会特别好。参考文献,以及所有...
    • 如果您担心可变类型,那么Counter 甚至一开始都不会工作。
    【解决方案4】:

    如果您碰巧已经在使用 numpy,或者如果使用它是一种选择,这里有另一种选择:

    In [309]: import numpy as np
    
    In [310]: a = [1, 2, 3, 3, 1, 3, 5, 4, 4, 4, 5, 5, 5]
    
    In [311]: vals, counts = np.unique(a, return_counts=True)
    
    In [312]: order = np.argsort(counts)[::-1]
    
    In [313]: np.repeat(vals[order], counts[order])
    Out[313]: array([5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2])
    

    该结果是一个 numpy 数组。如果您想以 Python 列表结尾,请调用数组的 tolist() 方法:

    In [314]: np.repeat(vals[order], counts[order]).tolist()
    Out[314]: [5, 5, 5, 5, 4, 4, 4, 3, 3, 3, 1, 1, 2]
    

    【讨论】:

      【解决方案5】:

      不有趣的方式...

      a = [1,1,2,3,3,3,4,4,4,5,5,5,5]
      
      from collections import Counter
      result = []
      for v, times in sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True):
          result += [v] * times
      

      一个班轮:

      reduce(lambda a, b: a + [b[0]] * b[1], sorted(Counter(a).iteritems(), key=lambda x: x[1], reverse=True), [])
      

      【讨论】:

        【解决方案6】:

        出现在数组和大小相等的集合中:

        rev=True
        
        arr = [6, 6, 5, 2, 9, 2, 5, 9, 2, 5, 6, 5, 4, 6, 9, 1, 2, 3, 4, 7 ,8 ,8, 8, 2]
        print arr
        
        arr.sort(reverse=rev)
        
        ARR = {}
        for n in arr:
          if n not in ARR:
            ARR[n] = 0
          ARR[n] += 1
        
        arr=[]
        for k,v in sorted(ARR.iteritems(), key=lambda (k,v): (v,k), reverse=rev):
          arr.extend([k]*v)
        print arr
        

        结果:

        [6, 6, 5, 2, 9, 2, 5, 9, 2, 5, 6, 5, 4, 6, 9, 1, 2, 3, 4, 7, 8, 8, 8, 2]
        [2, 2, 2, 2, 2, 6, 6, 6, 6, 5, 5, 5, 5, 9, 9, 9, 8, 8, 8, 4, 4, 7, 3, 1]
        

        【讨论】:

          猜你喜欢
          • 2021-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-16
          • 2020-02-01
          • 1970-01-01
          相关资源
          最近更新 更多