51

我正在尝试获取字典列表中所有键的列表,以便填写 csv.DictWriter 的 fieldnames 参数。

以前,我有这样的事情:

[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]

fieldnames = list[0].keys()用来获取列表中的第一个字典并提取它的键。

现在我有这样的东西,其中一个字典比其他字典有更多的键:值对(可能是任何结果)。新键是根据来自 API 的信息动态添加的,因此它们可能会出现在每个字典中,也可能不会出现,而且我事先不知道会有多少新键。

[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5, "height":4},
{"name": "Pam", "age": 7}
]

我不能只使用fieldnames = list[1].keys()它,因为它不一定是第二个具有额外键的元素。

一个简单的解决方案是找到具有最多键的字典并将其用于字段名,但如果您有这样的示例,这将不起作用:

[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5, "height":4},
{"name": "Pam", "age": 7, "weight":90}
]

第二个和第三个字典都有 3 个键,但最终结果应该是列表["name", "age", "height", "weight"]

4

6 回答 6

80
all_keys = set().union(*(d.keys() for d in mylist))

编辑:必须解压列表。现在修好了。

于 2012-07-09T16:38:59.113 回答
27

您的数据:

>>> LoD
[{'age': 10, 'name': 'Tom'}, 
 {'age': 5, 'name': 'Mark', 'height': 4}, 
 {'age': 7, 'name': 'Pam', 'weight': 90}]

这个集合理解会做到这一点:

>>> {k for d in LoD for k in d.keys()}
{'age', 'name', 'weight', 'height'}

它以这种方式工作。首先,创建 dict 键列表的列表:

>>> [list(d.keys()) for d in LoD]
[['age', 'name'], ['age', 'name', 'height'], ['age', 'name', 'weight']]

然后创建此列表列表的扁平化版本:

>>> [i for s in [d.keys() for d in LoD] for i in s]
['age', 'name', 'age', 'name', 'height', 'age', 'name', 'weight']

并创建一个消除重复的集合:

>>> set([i for s in [d.keys() for d in LoD] for i in s])
{'age', 'name', 'weight', 'height'}

可以简化为:

{k for d in LoD for k in d.keys()}
于 2012-07-09T16:47:07.197 回答
5
from itertools import chain

lis = [
    {"name": "Tom", "age": 10},
    {"name": "Mark", "age": 5, "height":4},
    {"name": "Pam", "age": 7, "weight":90}
]

# without qualification a dict iterates over its keys
# and set takes any iterable in its constructor
headers_as_set = set(chain.from_iterable(lis))

# you asked for a list
headers = list(
    set(chain.from_iterable(lis))
)
于 2018-11-02T03:09:19.673 回答
3
>>> lis=[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5, "height":4},
{"name": "Pam", "age": 7, "weight":90}
]
>>> {z for y in (x.keys() for x in lis) for z in y}
set(['age', 'name', 'weight', 'height'])
于 2012-07-09T16:45:00.177 回答
2

以下示例将提取密钥:

set_ = set()
for dict_ in dictionaries:
    set_.update(dict_.keys())
print set_
于 2012-07-09T16:41:07.980 回答
2

借用lis@AshwiniChaudhary 的回答,这里解释了如何解决问题。

>>> lis=[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5, "height":4},
{"name": "Pam", "age": 7, "weight":90}
]

直接在 dict 上迭代会返回其键,因此您无需调用keys()即可将它们取回,从而为列表中的每个元素保存一个函数调用和一个列表构造。

>>> {k for d in lis for k in d}
set(['age', 'name', 'weight', 'height'])

或使用itertools.chain

>>> from itertools import chain
>>> {k for k in chain(*lis)}
set(['age', 'name', 'weight', 'height'])
于 2012-07-09T16:48:52.597 回答