简体   繁体   English

从字典列表中提取所有键

[英]Extract all keys from a list of dictionaries

I'm trying to get a list of all keys in a list of dictionaries in order to fill out the fieldnames argument for csv.DictWriter.我正在尝试获取字典列表中所有键的列表,以便填写 csv.DictWriter 的字段名参数。

previously, I had something like this:以前,我有这样的事情:

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

and I was using fieldnames = list[0].keys() to take the first dictionary in the list and extract its keys.我正在使用fieldnames = list[0].keys()来获取列表中的第一个字典并提取其键。

Now I have something like this where one of the dictionaries has more key:value pairs than the others (could be any of the results).现在我有这样的东西,其中一个字典比其他字典有更多的键:值对(可能是任何结果)。 The new keys are added dynamically based on information coming from an API so they may or may not occur in each dictionary and I don't know in advance how many new keys there will be.新键是根据来自 API 的信息动态添加的,因此它们可能会或可能不会出现在每个字典中,我事先不知道会有多少新键。

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

I can't just use fieldnames = list[1].keys() since it isn't necessarily the second element that will have extra keys.我不能只使用fieldnames = list[1].keys()因为它不一定是第二个有额外键的元素。

A simple solution would be to find the dictionary with the greatest number of keys and use it for the fieldnames, but that won't work if you have an example like this:一个简单的解决方案是找到键数最多的字典并将其用于字段名,但如果您有这样的示例,那将不起作用:

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

where both the second and third dictionary have 3 keys but the end result should really be the list ["name", "age", "height", "weight"]第二个和第三个字典都有 3 个键,但最终结果实际上应该是列表["name", "age", "height", "weight"]

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

Edit : have to unpack the list. 编辑 :必须解压缩列表。 Now fixed. 现在修好了。

Your data: 你的数据:

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

This set comprehension will do it: 这种理解能够做到:

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

It works this way. 它以这种方式工作。 First, create a list of lists of the dict keys: 首先,创建一个dict键列表列表:

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

Then create a flattened version of this list of lists: 然后创建此列表列表的展平版本:

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

And create a set to eliminate duplicates: 并创建一个集来消除重复:

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

Which can be simplified to: 哪个可以简化为:

{k for d in LoD for k in d.keys()}
>>> 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'])
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))
)

The following example will extract the keys: 以下示例将提取键:

set_ = set()
for dict_ in dictionaries:
    set_.update(dict_.keys())
print set_

Borrowing lis from @AshwiniChaudhary's answer, here is an explanation of how you could solve your problem. 从@ AshwiniChaudhary的回答中借用lis ,这里是对如何解决问题的解释。

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

Iterating directly over a dict returns its keys, so you don't have to call keys() to get them back, saving a function call and a list construction per element in your list. 直接在dict上迭代返回其键,因此您不必调用keys()来取回它们,在列表中保存函数调用和每个元素的列表构造。

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

or use itertools.chain : 或使用itertools.chain

>>> from itertools import chain
>>> {k for k in chain(*lis)}
set(['age', 'name', 'weight', 'height'])

If order matters to you, read on...如果订单对您很重要,请继续阅读...

Input your data:输入您的数据:

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

Define your function:定义您的 function:

>>> def get_all_keys_in_order(list_of_dicts):
        ordered_keys = []
        for dict_ in list_of_dicts:
            for key in dict_:
                if key not in ordered_keys:
                    ordered_keys.append(key)
        return ordered_keys

Run your function to get output:运行你的 function 得到 output:

>>> get_all_keys_in_order(list_of_dicts)
['age', 'name', 'height', 'weight']

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM