Извлечение полей списка словарей в новый словарь с помощью 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,

Другие вопросы по тегам