添加计数器将删除密钥

2024-10-02 22:35:03 发布

您现在位置:Python中文网/ 问答频道 /正文

请看下面,为什么+=的实现会吹走我原来计数器中的一个键?在

>>> c = Counter({'a': 0, 'b': 0, 'c': 0})
>>> c.items()
[('a', 0), ('c', 0), ('b', 0)]
>>> c += Counter('abba')
>>> c.items()
[('a', 2), ('b', 2)]

我认为这至少是不礼貌的,在“X被数了0次”和“我们甚至没有计算X”之间有很大的区别。似乎collections.Counter根本不是一个计数器,它更像是一个多集。在

但是计数器是dict的一个子类,我们可以用零或负值构造它们:Counter(a=0, b=-1)。如果它实际上是一个“一包东西”,这不是被禁止的,限制init接受一个可散列项的iterable吗?在

为了进一步混淆问题,counter实现了update和{}方法,它们对+和{}运算符有不同的行为。这个班好像有身份危机!在

计数器是dict还是bag?


Tags: initcounter计数器updateitemsiterable子类collections
2条回答

source

def __add__(self, other):
    '''Add counts from two counters.

    >>> Counter('abbb') + Counter('bcc')
    Counter({'b': 4, 'c': 2, 'a': 1})

    '''
    if not isinstance(other, Counter):
        return NotImplemented
    result = Counter()
    for elem, count in self.items():
        newcount = count + other[elem]
        if newcount > 0:
            result[elem] = newcount
    for elem, count in other.items():
        if elem not in self and count > 0:
            result[elem] = count
    return result

计数器的实现似乎是删除和为零的非正键的键。由于默认值为零,并且源代码也为零,因此生成的dict不包含该键。

也许你可以用update得到同样的行为:

^{pr2}$

好像做了你想做的事。可能速度较慢,手工实现__add__方法会快得多。

Counters是一种多集。从^{} documentation

Several mathematical operations are provided for combining Counter objects to produce multisets (counters that have counts greater than zero). Addition and subtraction combine counters by adding or subtracting the counts of corresponding elements. Intersection and union return the minimum and maximum of corresponding counts. Each operation can accept inputs with signed counts, but the output will exclude results with counts of zero or less.

强调我的。

更进一步,它告诉您有关Counters的多集性质的更多细节:

Note: Counters were primarily designed to work with positive integers to represent running counts; however, care was taken to not unnecessarily preclude use cases needing other types or negative values. To help with those use cases, this section documents the minimum range and type restrictions.

[...]

  • The multiset methods are designed only for use cases with positive values. The inputs may be negative or zero, but only outputs with positive values are created. There are no type restrictions, but the value type needs to support addition, subtraction, and comparison.

因此Counter对象是同时是;字典包。然而,标准字典不支持加法,但是Counters支持加法,因此Counters并没有破坏字典在这里设置的优先级。

如果要保留零,请使用Counter.update()并传入另一个对象的Counter.elements()的结果:

c.update(Counter('abba').elements())

演示:

^{pr2}$

相关问题 更多 >