简体   繁体   中英

python nested dict comprehension with tuple as key

I have a dict like so:

{ ('name', 'user1'): 'foo',
  ('user', 'user1'): 'bar',
  ('name', 'user2'): 'bat',
  ('user', 'user2'): 'baz' }

and I would like to convert to:

{ 'user1': {'name': 'foo', 'user': 'bar'}, 
  'user2': {'name': 'bat', 'user': 'baz'} }

I can do this with a default dict easily, but I would like to use dict comprehension.

So far I have:

{user: {key:value for (key, user), value in my_dict.items()}}

But user is not inside the loop, so I name 'user' is not defined error.

How can I achieve this with dict comprehension?

A dict comprehension can be used if both key and value have a direct one-on-one relationship with the items in the sequence.

However, your output values are based on multiple entries in the input sequence. Unless you can group the items into a sequence per second value in the tuple key, you have to use a defaultdict setup.

Grouping is certainly possible with itertools.groupby() but that would require sorting, making that less performant compared to a defaultdict plus loop solution.

Using itertools.groupby :

from itertools import groupby

user = lambda item: item[0][1]

{user: {key[0]: value for key, value in grouped}
    for user, grouped in groupby(sorted(my_dict.items(), key=user), key=user)}

Output demo:

>>> {user: {key[0]: value for key, value in grouped}
...     for user, grouped in groupby(sorted(my_dict.items(), key=user), key=user)}
{'user2': {'name': 'bat', 'user': 'baz'}, 'user1': {'name': 'foo', 'user': 'bar'}}

This is a O(n log n) solution, versus the O(n) complexity of a defaultdict solution:

from collections import defaultdict

output = defaultdict(dict)

for (key, user), value in my_dict.iteritems():
    output[user][key] = value

this is working fine:

from __future__ import print_function
from itertools import groupby
from operator import itemgetter 

d=dict({('name', 'user1'): 'foo', ('user', 'user1'): 'bar',
        ('name', 'user2'): 'bat',
        ('user', 'user2'): 'baz' })

l = []
for key, val in d.items() :
    l.append([key[1], key[0], val])

l.sort(key=itemgetter(0))

d_ = dict()
for key, group in groupby(l, lambda x: x[0]):
    dic = dict()
    for thing in group:
        dic[thing[1]] = thing[2]
    d_[key] = dic

note that groupby from itertools will work only if list was previously sorted.

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