Извлеките все ключи из списка словарей

Я пытаюсь получить список всех ключей в списке словарей, чтобы заполнить аргумент fieldnames для csv.DictWriter.

раньше, у меня было что-то вроде этого:

[
{"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"]

Ответы

Ответ 1

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

Изменить: нужно распаковать список. Теперь исправлено.

Ответ 2

Ваши данные:

>>> 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()}

Ответ 3

В следующем примере будут извлечены ключи:

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

Ответ 4

>>> 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'])

Ответ 5

Заимствование 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'])