Dan
Dan

Reputation: 359

Python - Counting and adding items to a new dictionary

I have a list with quite a few entries that looks like this:

first_list = [
{'manager': 'manager1', 'template_id': '12345', 'template_title': 'Template Title1'},
{'manager': 'manager2', 'template_id': '12346', 'template_title': 'Template Title2'},
{'manager': 'manager23', 'template_id': '12345', 'template_title': 'Template Title1'}]

I want to count how many times a template_id is in the list, then add those to a new list of dictionaries (or if there is a better way to do this, I'm all ears).

So end result would be:

second_list = [
{'template_id': '12345', , 'template_title': 'Template Title1', 'count': '5'},
{'template_id': '12346', , 'template_title': 'Template Title2', 'count': '3'},
{'template_id': '12347', , 'template_title': 'Template Title3', 'count': '4''}]

I'm not sure how to iterate through this properly to get the count of the template_id. Any help is greatly appreciate. Thank you!

Upvotes: 2

Views: 166

Answers (5)

gold_cy
gold_cy

Reputation: 14216

So we can use itertools.groupby to achieve the desired result. The caveat for itertools.groupby is that your data must be pre-sorted on the grouped keys.

TO_KEEP = ['template_id', 'template_title']

def sort_key(item):
    return [item.get(k) for k in TO_KEEP]

results = []

sorted_data = sorted(first_list, key=sort_key)

for k, v in itertools.groupby(sorted_data, key=sort_key):
    temp = dict(zip(TO_KEEP, k))
    temp.update({'count': len(list(v))})
    results.append(temp)

print(results)

[{'template_id': '12345', 'template_title': 'Template Title1', 'count': 2},
 {'template_id': '12346', 'template_title': 'Template Title2', 'count': 1}]

Upvotes: 1

kederrac
kederrac

Reputation: 17322

you could use Counter from collections module with list comprehension:

from collections import Counter

count = Counter([e['template_id'] for e in first_list])
id_title = {e['template_id']: e['template_title'] for e in first_list}
second_list = [{'template_id': i, 'template_title': id_title[i], 'count': c} for i, c in count.items()]

output:

[{'template_id': '12345', 'template_title': 'Template Title1', 'count': 2},
 {'template_id': '12346', 'template_title': 'Template Title2', 'count': 1}]

Upvotes: 0

Mano
Mano

Reputation: 887

A possible solution, without utilizing external libraries:

counts = {}
for d in first_list:
    key = (d['template_id'], d['template_title'])
    counts[key] = counts.get(key, 0) + 1

second_list = [{'template_id': k[0], 'template_title': k[1], 'counts': v} for k, v in counts.items()]

Upvotes: 1

Nathan
Nathan

Reputation: 3648

You can do this ny first creating a dictionary of dictionaries:

dict_1 = {}
for sub_dict in first_list:
    template_id = sub_dict['template_id']
    template_title = sub_dict['template_title']
    if template_id not in dict_1:
        dict_1[template_id]  = {'template_id' : template_id, 'template_title': template_title, 'count' : 0}
    dict_1[template_id]['count'] += 1

Now all you need to do is convert this to a list:

second_list = list(dict_1.values())

Upvotes: 0

Laurent LAPORTE
Laurent LAPORTE

Reputation: 22952

You can sort the list by template_id and the group items by template_id using itertools.groupby, like this:

import itertools
import operator

first_list = [
    {"manager": "manager1", "template_id": "12345", "template_title": "Template Title1"},
    {"manager": "manager2", "template_id": "12346", "template_title": "Template Title2"},
    {"manager": "manager23", "template_id": "12345", "template_title": "Template Title1"},
]

get_template_id = operator.itemgetter("template_id")
first_list.sort(key=get_template_id)
second_list = []
for template_id, group in itertools.groupby(first_list, key=get_template_id):
    group = list(group)
    first = group[0]
    entry = {
        "template_id": template_id,
        "template_title": first["template_title"],
        "count": len(group),
    }
    second_list.append(entry)

print(second_list)

You get:

[
    {'template_id': '12345', 'template_title': 'Template Title1', 'count': 2},
    {'template_id': '12346', 'template_title': 'Template Title2', 'count': 1},
]

Upvotes: 1

Related Questions