Posts tagged with defaultdict

I am building something to sort and add values from an API response. I ended up going with an interesting structure, and I just want to make sure there's nothing inherently wrong with it.

from collections import defaultdict # Helps create a unique nested default dict object # for code readability def dict_counter():     return defaultdict(lambda: 0) # Creates the nested defaultdict object ad_data = defaultdict(dict_counter) # Sorts each instance into its channel, and # adds the dict values incrimentally for ad in example:        # Collects channel and metrics     channel = ad['ad_group']['type_']     metrics = dict(         impressions= int(ad['metrics']['impressions']),         clicks     = int(ad['metrics']['clicks']),         cost       = int(ad['metrics']['cost_micros'])     )          # Adds the variables     ad_data[channel]['impressions'] += metrics['impressions']     ad_data[channel]['clicks'] += metrics['clicks']     ad_data[channel]['cost'] += metrics['cost'] 

The output is as desired. Again, I just want to make sure I'm not reinventing the wheel or doing something really inefficient here.

defaultdict(<function __main__.dict_counter()>,             {'DISPLAY_STANDARD': defaultdict(<function __main__.dict_counter.<locals>.<lambda>()>,                          {'impressions': 14, 'clicks': 4, 'cost': 9}),              'SEARCH_STANDARD': defaultdict(<function __main__.dict_counter.<locals>.<lambda>()>,                          {'impressions': 6, 'clicks': 2, 'cost': 4})}) 

Here's what my input data would look like:

example = [     {         'campaign':          {             'resource_name': 'customers/12345/campaigns/12345',             'status': 'ENABLED',             'name': 'test_campaign_2'         },         'ad_group': {             'resource_name': 'customers/12345/adGroups/12345',             'type_': 'DISPLAY_STANDARD'},         'metrics': {             'clicks': '1', 'cost_micros': '3', 'impressions': '5'         },         'ad_group_ad': {             'resource_name': 'customers/12345/adGroupAds/12345~12345',             'ad': {                 'resource_name': 'customers/12345/ads/12345'             }         }     },     {         'campaign':          {             'resource_name': 'customers/12345/campaigns/12345',             'status': 'ENABLED',             'name': 'test_campaign_2'         },         'ad_group': {             'resource_name': 'customers/12345/adGroups/12345',             'type_': 'SEARCH_STANDARD'},         'metrics': {             'clicks': '2', 'cost_micros': '4', 'impressions': '6'         },         'ad_group_ad': {             'resource_name': 'customers/12345/adGroupAds/12345~12345',             'ad': {                 'resource_name': 'customers/12345/ads/12345'             }         }     },     {         'campaign':          {             'resource_name': 'customers/12345/campaigns/12345',             'status': 'ENABLED',             'name': 'test_campaign_2'         },         'ad_group': {             'resource_name': 'customers/12345/adGroups/12345',             'type_': 'DISPLAY_STANDARD'},         'metrics': {             'clicks': '3', 'cost_micros': '6', 'impressions': '9'         },         'ad_group_ad': {             'resource_name': 'customers/12345/adGroupAds/12345~12345',             'ad': {                 'resource_name': 'customers/12345/ads/12345'             }         }     } ] 

Thanks!