Извлечение полей списка словарей в новый словарь с помощью glom
У меня есть следующая очень упрощенная структура
elements = [{"id": "1", "counts": [1, 2, 3]},
{"id": "2", "counts": [4, 5, 6]}]
Я хотел бы быть в состоянии построить, используя glom
, новый словарь вида {<id>: <counts[pos]>}
например, для pos = 2
:
{"1": 3, "2": 6}
или, альтернативно, список / кортеж кортежей
[("1",3), ("2", 6)]
С помощью dict comprehension
это легко, но структура данных более сложна, и я хотел бы динамически указать, что извлечь. Предыдущий пример был бы самой простой вещью, которую я хотел бы достичь.
Через некоторое время мне удалось решить это следующим образом
from glom import glom, T
elements = [{"id": "1", "counts": [1,2,3]},{"id": "2", "counts": [4,5,6]}]
def extract(elements, pos):
extracted = glom(elements, ({"elements": [lambda v: (v["id"], v["counts"][pos])]}, T))
return dict(extracted["elements"])
Но это требует звонка dict
, Небольшое отклонение, которое пропускает косвенное обращение к словарю, будет
def extract(elements, pos):
extracted = glom(elements, (([lambda v: {v["id"]: v["counts"][pos]}]), T))
return {k: v for d in extracted for k, v in d.items()}
Теперь я мог бы использовать merge
функция вызывается на возвращаемые значения из glom
вызов
def extract(elements, pos):
return merge(glom(elements, (([lambda v: {v["id"]: v["counts"][pos]}]), T)))
Я довольно доволен этим, но есть ли лучший подход для этого? А с чем лучше я имею в виду создание единого чистого специфицируемого вызова? В конечном счете, я хотел бы иметь возможность определять во время выполнения удобным для пользователя способом значения словаря, т. Е. v["counts"][pos]
,
Улучшение этой идеи состояло бы в том, чтобы использовать вызываемый для вызова значения внутреннего словаря.
def counts_position(element, **kwargs):
return element["counts"][kwargs["pos"]]
def extract(elements, func, **kwargs):
return merge(glom(elements, (([lambda v: {v["id"]: func(v, **kwargs)}]), T)))
extract(values, counts_position, pos=2)
При этом то, что начинается с каждого элемента, может контролироваться извне.
1 ответ
Чтобы преобразовать список диктов с id
в каждом из них с помощью ключа с идентификатором можно использовать простое понимание:
{t["id"]: glom.glom(t, "counts.2") for t in elements}
Или, если вы хотите использовать glom для этого, используйте glom.Merge
вместе с glom.T
:
glom.glom(elements, glom.Merge([{T['id']: 'counts.2'}])))
Чтобы избежать лямбд, вы можете интерполировать pos
параметр в строку спецификации, например 'counts.%s' % pos
,