如何从具有不同长度列表的字典中创建词典列表

rau*_*aul 26 python dictionary list-comprehension python-itertools

我想从每个列表创建具有相同索引元素的词典列表。

我有这本字典:

d = {'name': ['bob', 'john', 'harry', 'mary'], 
     'age': [13, 19, 23], 
     'height': [164, 188], 
     'job': ['programmer']}
Run Code Online (Sandbox Code Playgroud)

所需的输出是:

d2 = [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}, 
      {'name': 'john', 'age': 19, 'height': 188}, 
      {'name': 'harry', 'age': 23},
      {'name': 'mary'}]
Run Code Online (Sandbox Code Playgroud)

我已经尝试过这样的事情:

d2 = [dict(zip(d, t)) for t in zip(*d.values())]
Run Code Online (Sandbox Code Playgroud)

但是我的输出是:

d2 = [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}]
Run Code Online (Sandbox Code Playgroud)

我认为这是因为列表的长度不同而引起的。

sch*_*ggl 23

您可以使用itertools.zip_longest和过滤None值:

from itertools import zip_longest

[{x: y for x, y in zip(d, t) if y is not None} for t in zip_longest(*d.values())]
# [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}, 
#  {'name': 'john', 'age': 19, 'height': 188}, 
#  {'name': 'harry', 'age': 23}, 
#  {'name': 'mary'}]
Run Code Online (Sandbox Code Playgroud)


Wil*_*sem 12

您可以zip_longest在这里使用:

from itertools import zip_longest

keys = d.keys()

d2 = [
    {k: v for k, v in zip(keys, vs) if v is not None}
    for vs in zip_longest(*d.values())
]
Run Code Online (Sandbox Code Playgroud)

如果值也可以None,我们可以使用虚拟值来规避它:

from itertools import zip_longest

keys = d.keys()
dummy = object()

d2 = [
    {k: v for k, v in zip(keys, vs) if v is not dummy}
    for vs in zip_longest(*d.values(), fillvalue=dummy)
]
Run Code Online (Sandbox Code Playgroud)

在这里,虚拟对象是一个对象,我们可以确定它不是其中的一部分d(因为我们在构造后再构造它d)。通过使用is比较,我们可以知道该值是否为“填充值”。

锡将给我们:

>>> d2
[{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}, {'name': 'john', 'age': 19, 'height': 188}, {'name': 'harry', 'age': 23}, {'name': 'mary'}]
Run Code Online (Sandbox Code Playgroud)


oli*_*x14 5

一个不使用 zip_longest 的简单解决方案,记录如下:

d = {'name': ['bob', 'john', 'harry', 'mary'], 'age': [13, 19, 23], 'height': [164, 188], 'job': ['programmer']}

recordset = [{k: v[i] for k, v in d.items() if i < len(v)} for i in range(max([len(l) for l in d.values()]))]

print(recordset)  # >> [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}, 
                        {'name': 'john', 'age': 19, 'height': 188}, 
                        {'name': 'harry', 'age': 23}, 
                        {'name': 'mary'}]
Run Code Online (Sandbox Code Playgroud)