【问题标题】:Counting occurrences without using collections.Counter在不使用 collections.Counter 的情况下计算出现次数
【发布时间】:2018-02-07 21:24:42
【问题描述】:

我正在尝试检索列表中出现频率最高和频率较低的元素。

frequency([13,12,11,13,14,13,7,11,13,14,12,14,14])

我的输出是:

([7], [13, 14])

我试过了:

import collections
s = [13,12,11,13,14,13,7,11,13,14,12,14,14]
count = collections.Counter(s)
mins = [a for a, b in count.items() if b == min(count.values())]
maxes = [a for a, b in count.items() if b == max(count.values())]
final_vals = [mins, maxes]

但我不想使用collections 模块并尝试更面向逻辑的解决方案。
你能帮我在没有收藏的情况下做吗?

【问题讨论】:

标签: python counting


【解决方案1】:

您可以使用tryexcept 方法和dict 来模拟Counter

def counter(it):
    counts = {}
    for item in it:
        try:
            counts[item] += 1
        except KeyError:
            counts[item] = 1
    return counts

或者您也可以使用dict.get,默认为0

def counter(it):
    counts = {}
    for item in it:
        counts[item] = counts.get(item, 0) + 1
    return counts

并且您应该在推导之外执行 min()max() 以避免重复计算该数量(函数现在是 O(n) 而不是 O(n^2)

def minimum_and_maximum_frequency(cnts):
    min_ = min(cnts.values())
    max_ = max(cnts.values())
    min_items = [k for k, cnt in cnts.items() if cnt == min_]
    max_items = [k for k, cnt in cnts.items() if cnt == max_]
    return min_items, max_items

这将按预期工作:

>>> minimum_and_maximum_frequency(counter([13,12,11,13,14,13,7,11,13,14,12,14,14]))
([7], [13, 14])

【讨论】:

    【解决方案2】:
    data = [13,12,11,13,14,13,7,11,13,14,12,14,14]
    occurrences = {}
    for i in data:
         if i in occurrences.keys():
                 occurrences[i] += 1
         else:
                 occurrences[i] = 1
    
    max_vals = [i for i in occurrences.keys() if occurrences[i] == max(occurrences.values())]
    min_vals = [i for i in occurrences.keys() if occurrences[i] == min(occurrences.values())]
    

    【讨论】:

      【解决方案3】:
      s = [13,12,11,13,14,13,7,11,13,14,12,14,14]
      
      occurrences = dict()
      
      for item in s:
      
          occurrences[item] = occurrences.setdefault(item, 0) + 1
      
      mins = [a for a, b in occurrences.items() if b == min(occurrences.values())]
      maxs = [a for a, b in occurrences.items() if b == max(occurrences.values())]
      
      final_vals = [mins, maxs]
      

      collections 中的defaultdict 更适合替换Counter 来计算列表中项目的出现次数。但是因为你限制了collections的使用。所以setdefault 处理KeyError 更优雅。

      【讨论】:

        【解决方案4】:

        这个怎么样:

        s = [13,12,11,13,14,13,7,11,13,14,12,14,14]
        freq_low = s.count(min(s, key=s.count))
        freq_high = s.count(max(s, key=s.count))
        mins = [a for a in set(s) if s.count(a) == freq_low]
        maxes = [a for a in set(s) if s.count(a) == freq_high]
        final_vals = [mins, maxes]
        

        【讨论】:

        • 那是O(n^4)(或者可能只是O(n^3)),而问题可以在O(n)中轻松解决。
        【解决方案5】:

        这是一个非常简单的解决方案,可能不是最有效的(?),而是一个简单的解决方案。

        data = get_data()
        freqs, numbers = {}, {}
        for i in data:
            freqs[i] = freqs.get(i, 0) + 1
        for n, c in freqs.items():
            numbers[c] = numbers.get(c, []) + [n]
        counts = list(numbers.keys())
        res = (numbers[min(counts)], numbers[max(counts)])
        

        让我们详细看看我们在上面的脚本中有什么,让我们从 您提供的示例数据,

        In [1]: data = [13,12,11,13,14,13,7,11,13,14,12,14,14]
        

        我们将使用两个字典,

        In [2]: freqs, numbers = {}, {}
        

        第一个在data 上迭代填充,它的键是 data 中的单个数字及其值是每个数字的频率 数据中的数字(参见freqs.get(…) 的脚注)

        In [3]: for i in data: freqs[i] = freqs.get(i, 0) + 1
        

        第二个只是第一个的反转,键是 频率和值是给定的数字列表 频率。

        In [4]: for n, c in freqs.items(): numbers[c] = numbers.get(c, []) + [n]
        
        In [5]: numbers
        Out[5]: {1: [7], 2: [12, 11], 4: [13, 14]}
        

        此时我们需要一个包含numbers 键的列表,即 发生次数

        In [6]: counts = list(numbers.keys())
        

        因为我们对 发生次数

        In [7]: [numbers[min(counts)], numbers[max(counts)]]
        Out[7]: [[7], [13, 14]]
        

        脚注:字典的.get(key, default_value) 方法 如果键不存在于字典中,则返回默认值, 我们将此功能与 0 默认值一起使用来汇总出现次数 单个数字,并与[],无效列表,建立一个列表 给定频率的所有数字。

        【讨论】:

        • 也许不是最快的,但每一步(计数、归一化和查找键的极值)都是O(n),所以总复杂度仍然是O(n) ...
        猜你喜欢
        • 1970-01-01
        • 2021-07-05
        • 1970-01-01
        • 2020-10-01
        • 1970-01-01
        • 2016-12-22
        • 2021-04-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多