user6136315
user6136315

Reputation: 705

Make a list of dictionaries based on existing dictionary

Wrote a script to fetch list of instances run by each user on AWS. I got a list a dictionaries. I would like to sort and list the number of instances run by each user(list_instances).

list_instances=[{'type': u't2.small', 'user': u'user1'},
     {'type': u'm4.large', 'user': u'user1'},
     {'type': u't2.medium', 'user': u'user1'},
     {'type': u't2.small', 'user': u'user1'},
     {'type': u'm4.large', 'user': u'user1'},
     {'type': u't2.small', 'user': u'user1'},
     {'type': u'm4.large', 'user': u'user2'},
     {'type': u'm4.large', 'user': u'user3'},
     {'type': u't2.medium', 'user': u'user2'},
     {'type': u't2.medium', 'user': u'user2'},
     {'type': u't2.small', 'user': u'user3'}]

created a two lists with user name and instance type.

names_list=[u'user1', u'user2', u'ben', u'user3', u'user4']

type_list=[u't2.small', u'm4.large', u'm4.large', u't2.medium', u't2.small', u'm4.large', u'm4.large', u't2.small']

Try:

val = 0
final_instances=[]
for ii in names_list:
    temp_dic = {}
    for jj in type_list:
        for kk in list_instances:
            if (ii == kk['user']) and (jj in kk):
                #print ii,kk['user'],jj,kk,kk[jj]
                temp_dic['user']=kk['user']
                temp_dic[jj]=val+kk[jj]
                final_a.append(temp_dic)
print (final_instances)

I didn't get the expected output as like below. My logic not efficient to get the expected result. Can someone help me on this. Thanks in advance!

Goal: final_instances= [{'user':u’user1’,’t2.small’:‘3’,’m4.large’:‘2’,’t2.medium’: ‘1’} {'user': u’user2’,’m4.large’: ‘1’,’t2.medium’: ‘2’} {'user': u’user3’,’t2.small’: ‘1’,’m4.large’: ‘1’}]

Upvotes: 1

Views: 62

Answers (2)

Moses Koledoye
Moses Koledoye

Reputation: 78554

You can use collections.Counter to take counts after grouping your original list of dicts by user:

from collections import Counter
from operator import itemgetter
from itertools import groupby
from pprint import pprint

f = itemgetter('user')
lst = []
for k, g in groupby(sorted(list_instances, key=f), f):
    c = Counter({u'user': k})
    c.update([d['type'] for d in g])
    lst.append(dict(c))

pprint(lst)

[{u'm4.large': 2, u't2.medium': 1, u't2.small': 3, u'user': u'user1'},
 {u'm4.large': 1, u't2.medium': 2, u'user': u'user2'},
 {u'm4.large': 1, u't2.small': 1, u'user': u'user3'}]

If you want the counts to end up as strings, you can use a dictionary comprehension to cast values in the counter before appending to the list.

...
d = {k: str(v) for k, v in c.items()}
lst.append(d)

Upvotes: 4

Pierce Darragh
Pierce Darragh

Reputation: 2200

Another option is to make final_instances a dictionary instead of a list, and then each count into int instead of str:

final_instances = {}

for instance in list_instances:
    user = instance['user']
    type = instance['type']
    data = final_instances.get(user)
    if data is None:
        data = {}
        final_instances[user] = data
    count = data.get(type, 0)
    data[type] = count + 1

(Note that this uses the variable name type which shadows a Python builtin. I used it because that's the name of your field, but in my own code I change field names to never shadow builtins.)

At the end of this, you get final_instances as:

{
    'user1': {'m4.large': 2, 't2.medium': 1, 't2.small': 3},
    'user2': {'m4.large': 1, 't2.medium': 2},
    'user3': {'m4.large': 1, 't2.small': 1},
}

Upvotes: 1

Related Questions