Ответ 1
all_keys = set().union(*(d.keys() for d in mylist))
Изменить: нужно распаковать список. Теперь исправлено.
Я пытаюсь получить список всех ключей в списке словарей, чтобы заполнить аргумент 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"]
all_keys = set().union(*(d.keys() for d in mylist))
Изменить: нужно распаковать список. Теперь исправлено.
Ваши данные:
>>> 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()}
В следующем примере будут извлечены ключи:
set_ = set()
for dict_ in dictionaries:
set_.update(dict_.keys())
print set_
>>> 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'])
Заимствование 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'])