Python 从计数器中删除最不常用的元素

Python 从计数器中删除最不常用的元素,python,counter,Python,Counter,在值小于某个值的计数器中,是否有“更快的方法”来删除键、值对 我已经做了以下工作: counter_dict = {k:v for k, v in counter_dict.items() if v > 5} 当前代码的主要问题是调用.items,这将创建所有项目的列表: 一种优化方法是使用而不是.items,以避免创建列表并再次遍历列表的代价 >>> from collections import Counter >>> cnt = Counter(

在值小于某个值的计数器中,是否有“更快的方法”来删除键、值对

我已经做了以下工作:

counter_dict = {k:v for k, v in counter_dict.items() if v > 5}

当前代码的主要问题是调用
.items
,这将创建所有项目的列表:

一种优化方法是使用而不是
.items
,以避免创建列表并再次遍历列表的代价

>>> from collections import Counter
>>> cnt = Counter("asbdasdbasdbadaasasdasadsa")
>>> {k:v for k,v in cnt.iteritems() if v > 5}
{'a': 10, 's': 7, 'd': 6}
另一种优化可能是不调用
.items
方法,而是迭代键并使用键访问值:

>>> from collections import Counter
>>> cnt = Counter("asbdasdbasdbadaasasdasadsa")
>>> {k:cnt[k] for k in cnt if cnt[k] > 5}
{'a': 10, 's': 7, 'd': 6}

如果我们尝试使用ipython中的
%timeit
测量差异,使用带有您提到的If条件的样本计数器,
将轻松获胜:

In [1]: import random

In [2]: from collections import Counter

In [3]: MILLION = 10**6

In [4]: cnt = Counter(random.randint(0, MILLION) for _ in xrange(MILLION))

In [5]: %timeit {k:v for k, v in cnt.iteritems() if v < 5}
10 loops, best of 3: 140 ms per loop

In [6]: %timeit {k:v for k, v in cnt.items() if v**2 < 5}
1 loops, best of 3: 290 ms per loop

In [7]: %timeit {k:cnt[k] for k in cnt if cnt[k] < 5}
1 loops, best of 3: 272 ms per loop

因此,您最好不要每次都重新创建整个词典:

to_remove = set()
for key, value in counter_dict.viewitems():
   if value <= 5:
      to_remove.add(key)

for key in to_remove:
    del counter_dict[key]

当dict应该开始过滤时,更改dict中的“阈值”属性对象。这或多或少有些过火了-因为您的检查仍将完成,只是时间会被稀释-但可能在使用对象时,您处于异步/多线程工作负载上,这可能会使其并行-但是如果您在代码的不同部分需要不同的阈值,这可能是一件好事。

您是否有特殊的性能问题?是的。柜台可以容纳超过500000个物品。根据10000个电话的调查显示,你的回答速度更快@mu比较慢,0.416秒,你的建议是0.715秒。
to_remove = set()
for key, value in counter_dict.viewitems():
   if value <= 5:
      to_remove.add(key)

for key in to_remove:
    del counter_dict[key]
class MyDict(dict):
   def __init__(*args, **kw):
       self.threshold = None
       super(MyDict,self).__init__(*args, **kw)
   def __getitem__(self, key):
       value = super(MyDict, self).__getitem__(key)
       if self.threshold is None or key > self.threshold:
          return value
       raise ItemError
   # the same for __contains__ and other interesting methods