Adding collections.Counter - int

I propose to add the following API to collections.Counter:

print(MyCounter("aaabb") - 2)
# => Counter({'a': 1})

Example implementation here

Why? What real-world code would use something like this? To be clear, to add this to the stdlib would need more than just one use case (i.e., “I’d use it in my code” isn’t enough) - it would have to simplify a non-trivial class of problems.

4 Likes

I needed that a few times, though not for something important. I think I did it like this:

from collections import Counter

ctr = Counter("aaabb")
ctr -= Counter(dict.fromkeys(ctr, 2))
print(ctr)  # Counter({'a': 1})

Saying ctr -= 2 would indeed be nicer.

1 Like

I find the idea of “subtracting 2” from a mapping object (which a Counter still is, even if it’s a very special mapping) to be very strange. I much prefer more explicit versions – either @pochmann’s suggestion:

c = Counter("aaabb")
new = c - Counter(dict.fromkeys(ctr, 2))

or

c = Counter("aaabb")
new = Counter({k: v - 2 for k, v in c.items()})
5 Likes

I’ve needed this a few times, but I don’t have “proof of usefulness” other than that.

@AlexWaygood to be identical your second implementation should be

c = Counter("aaabb")
new = +Counter({k: v - 2 for k, v in c.items()})

(Note the +)

I think that’s the next best alternative. The fromkeys variant is much less obvious IMO.

1 Like

How about c - Counter(list(c) * 2) or c - Counter({k: 2 for k in c}) ?

Lot of ways to concisely and explicitly make a Counter where everything is 2, and that avoids the +Counter syntax which looks very odd to me personally.

@jamestwebber I like the latter expression. The former is very inefficient for all but tiny counts.