List of dicts to/from dict of lists
I am looking to change back and forth between a dictionary of lists (all of the same length):
DL = {'a': [0, 1], 'b': [2, 3]}
and a list of dictionaries:
LD = [{'a': 0, 'b': 2}, {'a': 1, 'b': 3}]
I am looking for the cleanest way to switch between the two forms.
For those of you that enjoy clever/hacky one-liners.
Here is DL
to LD
:
v = [dict(zip(DL,t)) for t in zip(*DL.values())]
print(v)
and LD
to DL
:
v = {k: [dic[k] for dic in LD] for k in LD[0]}
print(v)
LD
to DL
is a little hackier since you are assuming that the keys are the same in each dict
. Also, please note that I do not condone the use of such code in any kind of real system.
Perhaps consider using numpy:
import numpy as np
arr = np.array([(0, 2), (1, 3)], dtype=[('a', int), ('b', int)])
print(arr)
# [(0, 2) (1, 3)]
Here we access columns indexed by names, e.g. 'a'
, or 'b'
(sort of like DL
):
print(arr['a'])
# [0 1]
Here we access rows by integer index (sort of like LD
):
print(arr[0])
# (0, 2)
Each value in the row can be accessed by column name (sort of like LD
):
print(arr[0]['b'])
# 2
If you're allowed to use outside packages, Pandas works great for this:
import pandas as pd
pd.DataFrame(DL).to_dict(orient="records")
Which outputs:
[{'a': 0, 'b': 2}, {'a': 1, 'b': 3}]
You can also use orient="list"
to get back the original structure
{'a': [0, 1], 'b': [2, 3]}
To go from the list of dictionaries, it is straightforward:
You can use this form:
DL={'a':[0,1],'b':[2,3], 'c':[4,5]}
LD=[{'a':0,'b':2, 'c':4},{'a':1,'b':3, 'c':5}]
nd={}
for d in LD:
for k,v in d.items():
try:
nd[k].append(v)
except KeyError:
nd[k]=[v]
print nd
#{'a': [0, 1], 'c': [4, 5], 'b': [2, 3]}
Or use defaultdict:
nd=cl.defaultdict(list)
for d in LD:
for key,val in d.items():
nd[key].append(val)
print dict(nd.items())
#{'a': [0, 1], 'c': [4, 5], 'b': [2, 3]}
Going the other way is problematic. You need to have some information of the insertion order into the list from keys from the dictionary. Recall that the order of keys in a dict is not necessarily the same as the original insertion order.
For giggles, assume the insertion order is based on sorted keys. You can then do it this way:
nl=[]
nl_index=[]
for k in sorted(DL.keys()):
nl.append({k:[]})
nl_index.append(k)
for key,l in DL.items():
for item in l:
nl[nl_index.index(key)][key].append(item)
print nl
#[{'a': [0, 1]}, {'b': [2, 3]}, {'c': [4, 5]}]
If your question was based on curiosity, there is your answer. If you have a real-world problem, let me suggest you rethink your data structures. Neither of these seems to be a very scalable solution.