ViaTech
ViaTech

Reputation: 2843

Compressing Dictionary into Dictionary of Dictionaries

I am trying to group these fields together by trailing numbers in the keys in order to turn this dictionary:

dict = {
'location_1': 'Living Room', 'status_1': True, 'information_1': 'good', 
'location_2': 'Dining Room', 'status_2': True, 'information_2': 'good', 
'location_3': 'Kitchen', 'status_3': True, 'information_3': 'good'
}

Into this:

new = {
'Living Room': {'status': True, 'information': 'good'},
'Dining Room': {'status': True, 'information': 'good'}, 
'Kitchen': {'status': True, 'information': 'good'}
}

How can I accomplish this?

Here was my attempt, I can't seem to get the logic right:

        json = dict()
        counter = 0
        so_far = {}
        for key, value in cleaned_data.items():
            v = key.split('_')[0]
            print(v)
            so_far[key.split('_')[0]] = value
            print(so_far)
            if counter != 0 and counter % 3 == 0:
                # I don't know where status or information are yet...
                json[so_far['location']] = {
                    'status': so_far['status'],
                    'information': so_far['information']
                }
                # reset
                so_far = dict()
            counter += 1
        print(json)

Upvotes: 2

Views: 85

Answers (2)

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

Short approach with old-good collections.defaultdict object:

import pprint
from collections import defaultdict

d = {
'location_1': 'Living Room', 'status_1': True, 'information_1': 'good',
'location_2': 'Dining Room', 'status_2': True, 'information_2': 'good',
'location_3': 'Kitchen', 'status_3': True, 'information_3': 'good'
}

groups = defaultdict(dict)
for k,v in d.items():
    name, idx = k.split('_')
    groups[idx][name] = v
res = {v.pop('location'): v for v in groups.values()}

pprint.pprint(res)

The output:

{'Dining Room': {'information': 'good', 'status': True},
 'Kitchen': {'information': 'good', 'status': True},
 'Living Room': {'information': 'good', 'status': True}}

Upvotes: 2

Ajax1234
Ajax1234

Reputation: 71451

You can use itertools.groupby:

from itertools import groupby
d = {'location_1': 'Living Room', 'status_1': True, 'information_1': 'good', 'location_2': 'Dining Room', 'status_2': True, 'information_2': 'good', 'location_3': 'Kitchen', 'status_3': True, 'information_3': 'good'}
new_d = [(a.split('_'), b) for a, b in d.items()]
new_data = [{c:d for [c, _], d in b} for _, b in groupby(sorted(new_d, key=lambda x:x[0][1]), key=lambda x:x[0][1])]
result = {i['location']:{'status':i['status'], 'information':i['information']} for i in new_data}

Output:

{'Living Room': {'status': True, 'information': 'good'}, 'Dining Room': {'status': True, 'information': 'good'}, 'Kitchen': {'status': True, 'information': 'good'}}

Edit: if the different information values in the final output are intentional, you can use zip:

info = ['good', 'awesome', 'yay']
result = {i['location']:{'status':i['status'], 'information':a} for i, a in zip(new_data, info)}

Output:

{'Living Room': {'status': True, 'information': 'good'}, 'Dining Room': {'status': True, 'information': 'awesome'}, 'Kitchen': {'status': True, 'information': 'yay'}}

Upvotes: 4

Related Questions