Как использовать Glom для вложенной структуры, как переместить словарные поля верхнего уровня в список словарей? - PullRequest
0 голосов
/ 15 апреля 2020

Это вопрос об использовании 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 для перемещения внешних, глобальных полей словаря 'date' и 'location' в список словарей для элементов.

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

[
 {'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'}
]

Увы, когда spe c достигает «элемента» словаря, другие значения перестают быть доступными, и объект 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 spe c?

1 Ответ

0 голосов
/ 21 апреля 2020

Хитрость заключается в том, чтобы передать цель в качестве глобальной области, таким образом, команда 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'}]
...