thelinuxer
thelinuxer

Reputation: 660

Grouping Python dictionaries in hierarchical form

I have a list of dictionaries and I wanted to group the data. I used the following:

group_list = []
for key, items in itertools.groupby(res, operator.itemgetter('dept')):
    group_list.append({key:list(items)})

For data that looks like this

[{'dept':1, 'age':10, 'name':'Sam'},
{'dept':1, 'age':12, 'name':'John'},
.
.
.
{'dept':2,'age':20, 'name':'Mary'},
{'dept':2,'age':11, 'name':'Mark'},
{'dept':2,'age':11, 'name':'Tom'}]

the output would be:

[{1:[{'dept':1, 'age':10, 'name':'Sam'},
    {'dept':1, 'age':12, 'name':'John'}],
 {2:[{'dept':2,'age':20, 'name':'Mary'},
    {'dept':2,'age':11, 'name':'Mark'},
    {'dept':2,'age':11, 'name':'Tom'}]
...
]

Now if I want to group using multiple keys say 'dept' and 'age', the above mentioned method returns

[{(2, 20): [{'age': 20, 'dept': 2, 'name': 'Mary'}]},
 {(2, 11): [{'age': 11, 'dept': 2, 'name': 'Mark'},
            {'age': 11, 'dept': 2, 'name': 'Tom'}]},
 {(1, 10): [{'age': 10, 'dept': 1, 'name': 'Sam'}]},
 {(1, 12): [{'age': 12, 'dept': 1, 'name': 'John'}]}]

The desired output would be:

[
    {
        2: {
            20: [
                {
                    'age': 20,
                    'dept': 2,
                    'name': 'Mary'
                }
            ]
        },
        {
            11: [
                {
                    'age': 11,
                    'dept': 2,
                    'name': 'Mark'
                },
                {
                    'age': 11,
                    'dept': 2,
                    'name': 'Tom'
                }
            ]
        }
    },
    {
        1: {
            10: [
                {
                    'age': 10,
                    'dept': 1,
                    'name': 'Sam'
                }
            ]
        },
        {
            12: [
                {
                    'age': 12,
                    'dept': 1,
                    'name': 'John'
                }
            ]
        }
    }
]

Can it be done with itertools? Or do I need to write that code myself?

Upvotes: 0

Views: 393

Answers (3)

thelinuxer
thelinuxer

Reputation: 660

Thanks everyone for your help. Here is how I did it:

import itertools, operator

l = [{'dept':1, 'age':10, 'name':'Sam'},
        {'dept':1, 'age':12, 'name':'John'},
        {'dept':2,'age':20, 'name':'Mary'},
        {'dept':2,'age':11, 'name':'Mark'},
        {'dept':2,'age':11, 'name':'Tom'}]

groups = ['dept', 'age', 'name'] 

groups.reverse()
def hierachical_data(data, groups):
    g = groups[-1]
    g_list = []
    for key, items in itertools.groupby(data, operator.itemgetter(g)):
        g_list.append({key:list(items)})
    groups = groups[0:-1]
    if(len(groups) != 0):
        for e in g_list:
            for k,v in e.items():
                e[k] = hierachical_data(v, groups)

    return g_list

print hierachical_data(l, groups)

Upvotes: 2

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798744

Absolutely. You just need to apply itertools.groupby() for the second criterion first, then the other.

Upvotes: 3

Amber
Amber

Reputation: 526733

You would need to write a (probably recursive) bit of code to do this yourself - itertools doesn't have a tree-builder in it.

Upvotes: 2

Related Questions