Markus
Markus

Reputation: 3375

Dict comprehension from dict to inverse dict

I have the following data:

a = {1: {'data': 243}, 2: {'data': 253}, 4: {'data':243}}

And I want to turn it around, so that the key is the values, and the data values is the keys. So first try:

b = dict(map(lambda id: (a[id]['data'], id, a))

But when I do this, the 1 gets overwritten by the 4, so result will be:

{243: 4, 253: 2}

So what I would like to get is a structure like this:

{243: [1, 4], 253: [2]}

How do I do this?

Upvotes: 0

Views: 76

Answers (2)

Tomalak
Tomalak

Reputation: 338228

This can be done with a dict comprehension and itertools.groupby(), but since dicts are not ordered, we must work with a sorted list, because groupby expects pre-sorted input.

from itertools import groupby

a = {1: {'data': 243}, 2: {'data': 253}, 4: {'data': 243}}

# key extractor function suitable for both sorted() and groupby()
keyfunc = lambda i: i[1]['data']

{g[0]: [i[0] for i in g[1]] for g in groupby(sorted(a.items(), key=keyfunc), key=keyfunc)}

here g is a grouping tuple (key, items), where

  • g[0] is whatever keyfunc extracts (in this case the 'data' value), and
  • g[1] is an iterable over dict items, i.e. (key, value) tuples, hence the additional list comprehension to extract the keys only.

result:

{243: [1, 4], 253: [2]}

Upvotes: 1

Praveenkumar
Praveenkumar

Reputation: 2182

I felt the below code is more readable and simpler way of approaching your problem.

from collections import defaultdict

a = {1: {'data': 243}, 2: {'data': 253}, 4: {'data':243}}

result = defaultdict(list)
for k, v in a.items():
    result[v['data']].append(k)

print(result)

Output:

defaultdict(<class 'list'>, {243: [1, 4], 253: [2]})

Upvotes: 3

Related Questions