[英]python list of dicts - convert each key-value as a individual dict
[英]Multivalue dict to list of individual dicts
具有以下字典結構
>>> d = {
'email': ['e_val1', 'e_val2', 'e_val3', 'e_val4', 'e_val5'],
'id' : ['i_val1', 'i_val2', 'i_val3', 'i_val4'],
'ref' : ['r_val1', 'r_val2', 'r_val3', 'r_val4']
}
什么是獲取以下各個口述列表的有效方法?
>>> l = [
{'email': 'e_val1', 'id': 'i_val1', 'ref': 'r_val1'},
{'email': 'e_val2', 'id': 'i_val2', 'ref': 'r_val2'},
{'email': 'e_val3', 'id': 'i_val3', 'ref': 'r_val3'},
{'email': 'e_val4', 'id': 'i_val4', 'ref': 'r_val4'},
{'email': 'e_val5', 'id': None, 'ref': None}
]
到目前為止,我嘗試過:
def split(d):
l, longest = [], False
for k, v in d.items():
longest = max(longest, len(v))
for pointer in range(longest):
r = {}
for k, v in d.items():
try:
r[k] = v[pointer]
except IndexError:
# current list is shorter than longest
r[k] = None
l.append(r)
return l
不久后成為
from itertools import izip_longest
def split(d):
"""
With Python < 2.7,
- itertools.izip_longest(*d.values())
might be substituted by map with None:
- map(None, *d.values())
"""
_zipper = lambda keys: lambda v: dict(zip(keys, v))
lmb = _zipper(d.keys())
return map(lmb,
itertools.izip_longest(*d.values()))
假設就性能而言,Python 2.7.x會是更好的方法?
>>> from timeit import timeit
>>> # with map
>>> timeit(setup="""
... d={'email': ['e_val1', 'e_val2', 'e_val3', 'e_val4', 'e_val5'],
... 'id': ['i_val1', 'i_val2', 'i_val3', 'i_val4'],
... 'ref': ['r_val1', 'r_val2', 'r_val3', 'i_val4']};
... _zipper=lambda keys: lambda v: dict(zip(keys, v))""",
... stmt="""
... lmb=_zipper(d.keys());
... map(lmb, map(None, *d.values()))""")
16.14903998374939
>>> # with itertools.izip_longest
>>> timeit(setup="""
... d={'email': ['e_val1', 'e_val2', 'e_val3', 'e_val4', 'e_val5'],
... 'id': ['i_val1', 'i_val2', 'i_val3', 'i_val4'],
... 'ref': ['r_val1', 'r_val2', 'r_val3', 'i_val4']};
... _zipper=lambda keys: lambda v: dict(zip(keys, v))""",
... stmt="""
... lmb=_zipper(d.keys());
... map(lmb, izip_longest(*d.values()))""")
18.98265790939331
PS對於那些好奇的人,初始dict是Django MultiValue QueryDict,其中包含許多具有相同名稱的<input>
值。
使用itertools.zip_longest
和列表理解:
[{'email': i, 'id': j, 'ref': k} for (i, j, k) in itertools.zip_longest(d.get('email'), d.get('id'), d.get('ref'))]
例:
>>> d
{'ref': ['r_val1', 'r_val2', 'r_val3', 'r_val4'], 'id': ['i_val1', 'i_val2', 'i_val3', 'i_val4'], 'email': ['e_val1', 'e_val2', 'e_val3', 'e_val4', 'e_val5']}
>>> [{'email': i, 'id': j, 'ref': k} for (i, j, k) in itertools.zip_longest(d.get('email'), d.get('id'), d.get('ref'))]
[{'ref': 'r_val1', 'id': 'i_val1', 'email': 'e_val1'}, {'ref': 'r_val2', 'id': 'i_val2', 'email': 'e_val2'}, {'ref': 'r_val3', 'id': 'i_val3', 'email': 'e_val3'}, {'ref': 'r_val4', 'id': 'i_val4', 'email': 'e_val4'}, {'ref': None, 'id': None, 'email': 'e_val5'}]
沒有硬編碼的值:timeit:5.15033793449
def form_dict(key_index):
each_dict = {}
for k in d.keys():
if key_index < len(d[k]):
each_dict[k] = d[k][key_index]
else:
each_dict[k] = None
return each_dict
def get_converted_list():
Max = max([len(v) for v in d.values()])
return map(form_dict, range(0, Max))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.