Используя Glom во вложенной структуре, как переместить поля словаря верхнего уровня в список словарей?

Это вопрос об использовании Glom (https://github.com/mahmoud/glom/)

У меня есть словарь, в котором есть список других словарей.

{'date': '2020-01-01',
 'location': 'A',
 'items': [
     {'name': 'A', 'id': 'A1'},
     {'name': 'B', 'id': 'B1'},
     {'name': 'C', 'id': 'C1'}
]}

Я хотел бы использовать Glom, чтобы переместить внешние, глобальные словарные поля "дата" и "местоположение" в список словарей для элементов.

Это конечный результат, которого я пытаюсь достичь

[
 {'name': 'A', 'id': 'A1', 'date': '2020-01-01', 'location': 'A'},
 {'name': 'B', 'id': 'B1', 'date': '2020-01-01', 'location': 'A'},
 {'name': 'C', 'id': 'C1', 'date': '2020-01-01', 'location': 'A'}
]

Увы, когда спецификация достигает "элемента" словаря, другие значения становятся недоступными, и вместо этого для объекта T устанавливается внутреннее значение.

from glom import glom, T

def update_dict(x, other_dict):
    x.update({'date': other_dict['date'], 'location': other_dict['location']})  
    return x.copy()

spec = (T, 'items', [(lambda x: update_dict(x, T()))])

data = {'date': '2020-01-01',
       'location': 'A',
       'items': [{'name': 'A', 'id': 'A1'},
                 {'name': 'B', 'id': 'B1'},
                 {'name': 'C', 'id': 'C1'}]}

glom(data, spec)  # print this

возвращается

[{'name': 'A', 'id': 'A1', 'date': T()['date'], 'location': T()['location']},
 {'name': 'B', 'id': 'B1', 'date': T()['date'], 'location': T()['location']},
 {'name': 'C', 'id': 'C1', 'date': T()['date'], 'location': T()['location']}]

Что бесполезно.

Обновить словари с помощью обычного кода Python несложно, но есть ли способ сделать это в рамках спецификации Glom?

1 ответ

Решение

Уловка состоит в том, чтобы передать цель как глобальную область видимости, таким образом, Assign команда может получить доступ к полной цели.

from glom import S, glom, Assign, Spec

spec = ('items', 
        [Assign( 'date', Spec(S['date']))], 
        [Assign( 'location', Spec(S['location']))]
       )

target = {'date': '2020-04-01',
     'location': 'A',
     'items': [
         {'name': 'A', 'id': 'A1'},
         {'name': 'B', 'id': 'B1'},
         {'name': 'C', 'id': 'C1'}
    ]}

spec = Spec(('items', [Assign( 'date', Spec(S['date']))], [Assign( 'location', Spec(S['location']))]))

glom(target, spec, scope=target)

Результаты в

[{'name': 'A', 'id': 'A1', 'date': '2020-04-01', 'location': 'A'},
 {'name': 'B', 'id': 'B1', 'date': '2020-04-01', 'location': 'A'},
 {'name': 'C', 'id': 'C1', 'date': '2020-04-01', 'location': 'A'}]
Другие вопросы по тегам