简体   繁体   中英

What Is a Pythonic Way to Build a Dict of Dictionary-Lists by Attribute?

I'm looking for pythonic way to convert list of tuples which looks like this:

 res = [{type: 1, name: 'Nick'}, {type: 2, name: 'Helma'}, ...]

To dict like this:

 {1: [{type: 1, name: 'Nick'}, ...], 2: [{type: 2, name: 'Helma'}, ...]}

Now i do this with code like this ( based on this question ):

 d = defaultdict(list) 
 for v in res:
    d[v["type"]].append(v)

Is this a Pythonic way to build dict of lists of objects by attribute?

I agree with the commentators that here, list comprehension will lack, well, comprehension.

Having said that, here's how it can go:

import itertools

a = [{'type': 1, 'name': 'Nick'}, {'type': 2, 'name': 'Helma'}, {'type': 1, 'name': 'Moshe'}]
by_type = lambda a: a['type']  
>>> dict([(k, list(g)) for (k, g) in itertools.groupby(sorted(a, key=by_type), key=by_type)])
{1: [{'name': 'Nick', 'type': 1}, {'name': 'Moshe', 'type': 1}], ...}

The code first sorts by 'type' , then uses itertools.groupby to group by the exact same critera.


I stopped understanding this code 15 seconds after I finished writing it :-)

You could do it with a dictionary comprehension, which wouldn't be as illegible or incomprehensible as the comments suggest (IMHO):

# A collection of name and type dictionaries
res = [{'type': 1, 'name': 'Nick'},
       {'type': 2, 'name': 'Helma'},
       {'type': 3, 'name': 'Steve'},
       {'type': 1, 'name': 'Billy'},
       {'type': 3, 'name': 'George'},
       {'type': 4, 'name': 'Sylvie'},
       {'type': 2, 'name': 'Wilfred'},
       {'type': 1, 'name': 'Jim'}]

# Creating a dictionary by type
res_new = {
    item['type']: [each for each in res
                   if each['type'] == item['type']]
    for item in res
}

>>>res_new
{1: [{'name': 'Nick', 'type': 1},
     {'name': 'Billy', 'type': 1},
     {'name': 'Jim', 'type': 1}],
 2: [{'name': 'Helma', 'type': 2},
     {'name': 'Wilfred', 'type': 2}],
 3: [{'name': 'Steve', 'type': 3},
     {'name': 'George', 'type': 3}],
 4: [{'name': 'Sylvie', 'type': 4}]}

Unless I missed something, this should give you the result you're looking for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM