9
\$\begingroup\$

I need to convert a list of dictionaries to a dictionary of dictionaries, with a particular item as the new key.

This is the way I'm currently doing it:

>>> a
[{'bar': 'baz', 'id': 'foo'}, {'bar': 'baz', 'id': 'qux'}]
>>> {
    item['id']:{
        sub_item:item[sub_item] for sub_item in item if sub_item != 'id'
    } for item in a}

{'qux': {'bar': 'baz'}, 'foo': {'bar': 'baz'}}

However, this looks really ugly to me. Is there a more elegant way to do this?

\$\endgroup\$
11
\$\begingroup\$

While using methods with side effects in list- or dict-comprehensions is generally frowned upon, in this case you could make use of dict.pop to get the id and at the same time remove it from the dictionary.

>>> a = [{'bar': 'baz', 'id': 'foo'}, {'bar': 'baz', 'id': 'qux'}]
>>> {d.pop("id"): d for d in a}
{'qux': {'bar': 'baz'}, 'foo': {'bar': 'baz'}}

Keep in mind, though, that this will alter the dictionary in-place, i.e. afterwards:

>>> a
[{'bar': 'baz'}, {'bar': 'baz'}]

If you do not want to alter the original dictionaries, use map(dict, a) to create copies before poping elements from those, leaving the original dicts in a as they were.

>>> {d.pop("id"): d for d in map(dict, a)}
{'qux': {'bar': 'baz'}, 'foo': {'bar': 'baz'}}
\$\endgroup\$
6
\$\begingroup\$

I would recommend an object-oriented approach to this.

>>> class Buz(object):
...     def __init__(self, bar):
...             self.bar = bar
...
>>> buzdict = {'foo':Buz('baz'), 'qux':Buz('baz')}
>>> buzdict.get('foo').bar
'baz'
>>> buzdict.get('qux').bar
'baz'
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.