Summing list of counters in python
Question:
I am looking to sum a list of counters in python. For example to sum:
counter_list = [Counter({"a":1, "b":2}), Counter({"b":3, "c":4})]
to give Counter({'b': 5, 'c': 4, 'a': 1})
I can get the following code to do the summation:
counter_master = Counter()
for element in counter_list:
counter_master = counter_master + element
But I am confused as to why counter_master = sum(counter_list)
results in the error TypeError: unsupported operand type(s) for +: 'int' and 'Counter'
? Given it is possible to add counters together, why is it not possible to sum them?
Answers:
The sum
function has the optional start argument which defaults to 0. Quoting the linked page:
sum(iterable[, start])
Sums start and the items of an iterable from left to right and returns
the total
Set start to (empty) Counter
object to avoid the TypeError
:
In [5]: sum(counter_list, Counter())
Out[5]: Counter({'b': 5, 'c': 4, 'a': 1})
This version was faster in my experience. This is upper bound by O(log(n)).
def sum_counters(counter_list):
'''
Recursive counter with a O(log(n)) Complexity
'''
if len(counter_list) > 10:
counter_0 = sum_counters(counter_list[:int(len(counter_list)/2)])
counter_1 = sum_counters(counter_list[int(len(counter_list)/2):])
return sum([counter_0, counter_1], Counter())
else:
return sum(counter_list, Counter())
global_counter = sum_counters(counter_list)
I am looking to sum a list of counters in python. For example to sum:
counter_list = [Counter({"a":1, "b":2}), Counter({"b":3, "c":4})]
to give Counter({'b': 5, 'c': 4, 'a': 1})
I can get the following code to do the summation:
counter_master = Counter()
for element in counter_list:
counter_master = counter_master + element
But I am confused as to why counter_master = sum(counter_list)
results in the error TypeError: unsupported operand type(s) for +: 'int' and 'Counter'
? Given it is possible to add counters together, why is it not possible to sum them?
The sum
function has the optional start argument which defaults to 0. Quoting the linked page:
sum(iterable[, start])
Sums start and the items of an iterable from left to right and returns
the total
Set start to (empty) Counter
object to avoid the TypeError
:
In [5]: sum(counter_list, Counter())
Out[5]: Counter({'b': 5, 'c': 4, 'a': 1})
This version was faster in my experience. This is upper bound by O(log(n)).
def sum_counters(counter_list):
'''
Recursive counter with a O(log(n)) Complexity
'''
if len(counter_list) > 10:
counter_0 = sum_counters(counter_list[:int(len(counter_list)/2)])
counter_1 = sum_counters(counter_list[int(len(counter_list)/2):])
return sum([counter_0, counter_1], Counter())
else:
return sum(counter_list, Counter())
global_counter = sum_counters(counter_list)