2017-08-30 53 views
0

我正在尝试检索列表中最频繁且频率较低的元素。不使用集合来计算发生次数。计数器

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模块,并尝试更多的面向逻辑的解决方案。
你可以帮我做一下没有收藏吗?

+0

对于“max occuring element”(aka。_mode_),看看这个问题:[查找列表模式](https://stackoverflow.com/questions/10797819/finding-the-mode-of -一个列表)。 –

+0

[查找列表模式]的可能重复(https://stackoverflow.com/questions/10797819/finding-the-mode-of-a-list) – araknoid

回答

0
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())] 
2

你可以使用一个tryexcept方法与dict来模拟一个Counter

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

或alternativly你可以使用dict.get0默认:

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

defaultdictcollections更适合代替Counter来计算列表项的出现。但是因为你限制使用collections。所以setdefault更加优雅,以应对KeyError

0

这个怎么样:

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

这就是'O(n^4)'(或者可能是只是'O(n^3)'),而这个问题可以在'O(n)'中很容易解决。 – MSeifert

0

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

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及其值t他在数据中的每个 号码(见fotnote为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默认值将各个数字的出现次数 与[](void列表)相加以构建一个列出所有给定频率的数字的 。

+0

也许不是最快的一个,但是每一步(计数,结块和查找键的极值)都是'O(n)',所以总的复杂度仍然是'O(n)'... – gboffi