python - collections.Counter addition error with counter of counters summation -


suppose have code snippet follows:

from collections import namedtuple, counter  experiment = namedtuple('experiment', ['day', 'distribution']) labresults = namedtuple('labresults', ['lab_name', 'experiments_data'])  lab_results_list_good = [     labresults(         'lab a',          [             experiment('first_day',  counter('abc')),             experiment('second_day', counter(''))         ],     ),     labresults(         'lab b',         [             experiment('first_day', counter('')),             experiment('second_day', counter('a')),         ]     ) ]  lab_results_list_bad = [     labresults(         'lab a',          [             experiment('first_day', counter('abc')),             experiment('second_day', counter('def'))         ],     ),     labresults(         'lab b',         [             experiment('first_day', counter('ghi')),         ]     ) ]   def merge_distributions(lab_results_list):     day_to_distribution_report = counter()     lab_result in lab_results_list:          curr_day_to_dist = counter({exp.day: exp.distribution exp in lab_result.experiments_data})         day_to_distribution_report += curr_day_to_dist     return day_to_distribution_report 

first case works fine , second case doesn't work:

in [2]: print merge_distributions(lab_results_list_good) counter({'first_day': counter({'a': 1, 'c': 1, 'b': 1}), 'second_day': counter({'a': 1})})  in [3]: print merge_distributions(lab_results_list_bad) --------------------------------------------------------------------------- typeerror                                 traceback (most recent call last) <ipython-input-3-969bd085f2e5> in <module>() ----> 1 print merge_distributions(lab_results_list_bad)  <ipython-input-1-0bdc39e8c846> in merge_distributions(lab_results_list)      42      43         curr_day_to_dist = counter({exp.day: exp.distribution exp in lab_result.experiments_data}) ---> 44         day_to_distribution_report += curr_day_to_dist      45     return day_to_distribution_report  /usr/local/cellar/python/2.7.13/frameworks/python.framework/versions/2.7/lib/python2.7/collections.pyc in __add__(self, other)     642         result = counter()     643         elem, count in self.items(): --> 644             newcount = count + other[elem]     645             if newcount > 0:     646                 result[elem] = newcount  typeerror: unsupported operand type(s) +: 'counter' , 'int' 

in python 2 doesn't works second case, in python 3 doesn't works both.

so question bad idea merge counter of counters python 3 fails both cases run? seems bug counter object support additions.

edit find out fast fix merge_distribution function:

def merge_distributions(lab_results_list):     day_range = {exp.day lab_result in lab_results_list exp in lab_result.experiments_data}     day_to_distribution_report = counter()     lab_result in lab_results_list:          curr_day_to_dist = counter({exp.day: exp.distribution exp in lab_result.experiments_data})         map(lambda day: curr_day_to_dist.setdefault(day, counter()), day_range)         day_to_distribution_report += curr_day_to_dist     return day_to_distribution_report 

why python sources not default?

if counter doesn't have property, default 0, not counter()

>>> collections import counter >>> c = counter({ ...     'a': counter(), 'b': counter(), ... }) >>> d = counter({ ...     'a': counter() ... }) >>> c['b'] counter() >>> d['b'] 0 >>> c['b'] + d['b'] traceback (most recent call last):   file "<stdin>", line 1, in <module> typeerror: unsupported operand type(s) +: 'counter' , 'int' >>>  

here defaultcounter implements:

from collections import counter   class defaultcounter(counter):      def __add__(self, other):         if not isinstance(other, counter):             if other == 0:                 other = counter()             else:                 return notimplemented         result = counter()         elem, count in self.items():             newcount = count + other[elem]             if newcount > 0:                 result[elem] = newcount         elem, count in other.items():             if elem not in self , count > 0:                 result[elem] = count         return result  >>> m import defaultcounter >>> = defaultcounter({'a': defaultcounter(), 'b': defaultcounter()}) >>> b = defaultcounter({'a': defaultcounter()}) >>>  >>> + b counter({'a': counter(), 'b': counter()}) # not raise anymore. ^_^ 

Comments

Popular posts from this blog

PHP and MySQL WP -

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

go - golang pprof for c library code -