Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can counters in python be compared like this?

If you compare two counters like this:

counter_a == counter_b

You get either True or False. However, if you were to compare them using reduce/ operator.eq, you get False. Can someone please enlighten me about what's going on here?

Here's an example:

>>> import collections
>>> import operator
>>> a = ['ab', 'ab', 'ab']
>>> b = ['bc', 'ab', 'something']
>>> counters_a = map(collections.Counter, a)
[Counter({'a': 1, 'b': 1}), Counter({'a': 1, 'b': 1}), Counter({'a': 1, 'b': 1})]
>>> counters_b = map(collections.Counter, b)
[Counter({'c': 1, 'b': 1}), Counter({'a': 1, 'b': 1}), Counter({'e': 1, 'g': 1, 'i': 1, 'h': 1, 'm': 1, 'o': 1, 'n': 1, 's': 1, 't': 1})]
>>> counters_a[0] == counters_a[1]
True
>>> counters_b[0] == counters_b[1]
False
>>> reduce(operator.eq, [1, 1, 1])
True
>>> reduce(operator.eq, [1, 1, 2])
False
>>> reduce(operator.eq, counters_b)
**False**
>>> reduce(operator.eq, counters_a)
**False**
like image 225
yesudeep Avatar asked Jun 26 '26 09:06

yesudeep


1 Answers

I think you are confused about what reduce does. Given your input, reduce does this:

((counters_a[0] == counters_a[1]) == counters_a[2])

so it compares a boolean True or False with another counter. Counters are never equal to a boolean value. reduce runs the operation on the first two elements, then takes the result of that operation and uses it as the input for the next loop, together with the next element of the list.

Because the Python boolean type is a subclass of int, it happens to work for 1 (True == 1 is True in python). Do the same with all 2 values and it'll fail:

>>> reduce(operator.eq, [2, 2, 2])
False

If you want to test if all counters are the same, use all() instead:

>>> all(counters_a[0] == c for c in counters_a[1:])
True
>>> all(counters_b[0] == c for c in counters_b[1:])
False
like image 63
Martijn Pieters Avatar answered Jun 27 '26 21:06

Martijn Pieters