Alex
Alex

Reputation: 6037

Transform dictionary to list of items

I have a dictionary that looks like this:

{'a':[1,2,3], 'b':[4,5,6], 'c': [7,8,9], 'd': [10,11,12]}

but I need it in this format:

[{'a':1, 'b':4, 'c':7, 'd':10},
 {'a':2, 'b':5, 'c':8, 'd':11),
 {'a':3, 'b':6, 'c':9, 'd':12},
 ]

How could this be done (probably using list comprehension)?

What I had so far (but is not working):

[{k:v[i] for k,v in x.items()}
  for i in x 
]

Upvotes: 0

Views: 89

Answers (4)

Alex Waygood
Alex Waygood

Reputation: 7509

[{k: v[i] for k, v in original_dict.items()} for i in range(len(next(iter(original_dict.values()))))]

^That obviously only works if you know all the lists will be of the same length.

If you know the length of the lists in advance, you can simplify it:

[{k: v[i] for k, v in original_dict.items()} for i in range(3)]

If you don't know the length of the lists in advance, and you also can't be certain that all lists will be of the same length, you can do this:

from collections import defaultdict
new_dict = defaultdict(dict)

for k, v in original_dict.items():
    for i, sub_value in enumerate(v):
        new_dict[i][k] = sub_value

results = list(new_dict.values())

This last one you could also do with plain old dict.setdefault(), but using collections.defaultdict will likely be faster.

Upvotes: 3

LuisAFK
LuisAFK

Reputation: 957

This uses two list comprehensions:

[{k: v[i] for k, v in d.items()} for i in range(len(d[list(d.keys())[0]]))]

Output:

[
    {"a": 1, "b": 4, "c": 7, "d": 10},
    {"a": 2, "b": 5, "c": 8, "d": 11},
    {"a": 3, "b": 6, "c": 9, "d": 12},
]

Upvotes: 1

user2390182
user2390182

Reputation: 73450

A rather simple comprehension would be:

d = {'a':[1,2,3], 'b':[4,5,6], 'c': [7,8,9], 'd': [10,11,12]}

[{k: d[k][i] for k in d} for i in range(next(map(len, d.values())))]
# [{'a': 1, 'b': 4, 'c': 7, 'd': 10}, 
#  {'a': 2, 'b': 5, 'c': 8, 'd': 11}, 
#  {'a': 3, 'b': 6, 'c': 9, 'd': 12}]

Upvotes: 2

Chris
Chris

Reputation: 29742

One way using operator.itemgetter:

from operator import itemgetter

k = d.keys()
[dict(zip(k, i)) for i in zip(*itemgetter(*k)(d))]

Output:

[{'a': 1, 'b': 4, 'c': 7, 'd': 10},
 {'a': 2, 'b': 5, 'c': 8, 'd': 11},
 {'a': 3, 'b': 6, 'c': 9, 'd': 12}]

Upvotes: 4

Related Questions