Добавление списка словарей с дополнительным ключом в одном словаре и вложенным dict в качестве значения - PullRequest
1 голос
/ 10 июля 2019

У меня есть схема, и у меня есть список вложенных полей, которые должны быть в ней. В основном то, что у меня есть:

[{'name': 'a', 'type': 'string'}, 
{'name': 'b', 'type': 'string'}, 
{'name': 'c', 'type': 'string'}, 
{'name': 'd', 'type': 'string'}, 
{'name': 'e', 'type': 'string'}, 
{'name': 'attr', 'type': 'string'}, 
{'name': 'f', 'type': 'string'},
{'name': 'g', 'type': 'string'}, 
{'name': 'h', 'type': 'string'}, 
{'name': 'i', 'type': 'string'}, 
{'name': 'j', 'type': 'string'}, 
{'name': 'k', 'type': 'string'}]

Но когда "name" равно "attr", я хочу добавить к нему другую пару k-v словаря с ключом в качестве "полей" и значением в качестве другого вложенного списка словарей в том же формате, что и выше. Это будет выглядеть так:

[{'name': 'a', 'type': 'string'}, 
{'name': 'b', 'type': 'string'}, 
{'name': 'c', 'type': 'string'}, 
{'name': 'd', 'type': 'string'}, 
{'name': 'e', 'type': 'string'}, 
{'name': 'attr', 'type': 'string', 'fields': [{'name': 'aa',....}], 
{'name': 'f', 'type': 'string'},
{'name': 'g', 'type': 'string'}, 
{'name': 'h', 'type': 'string'}, 
{'name': 'i', 'type': 'string'}, 
{'name': 'j', 'type': 'string'}, 
{'name': 'k', 'type': 'string'}]

Ниже master_schema_set и nestedschemaset были просто наборами, которые я конвертировал.

finalschema = [{'name':l} for l in master_schema_set]
finalschemanested = [{'name':l} for l in nestedschemaset]

for i in finalschema:
    i.update({"type":'string'}) #all types will always be string
    for item,val in i.items():
        if val == 'attr':
            i.update({'fields':finalschemanested})

Выполнение этого дает мне ошибку «словарь изменил размер во время итерации», но в конечном итоге это то, что я хочу. Какой лучший способ добиться этого?

Ответы [ 3 ]

2 голосов
/ 10 июля 2019

Попробуйте:

for i in finalschema:
    i.update({"type":'string'}) #all types will always be string
    if i['name'] == 'attr':
        i.update({'fields':finalschemanested})
  • Примечание: поскольку состояния ошибки не пытаются обновлять dict во время итерации объекта.
0 голосов
/ 10 июля 2019

Повторение Dict и переключение на одно и то же Dict не очень хорошая идея.См. блог Кристофа Цвершке.

Вам необходимо изменить код из этого типа шаблона.Это верно для списка и другой структуры данных.в python2 он никогда не отображается как ошибка или предупреждение, и цикл проходит бесконечно.Приведи один из моих ответов Раджа Шактиян

0 голосов
/ 10 июля 2019

изменение i, в то время как перебор его пар ключ / значение запрещен, обходной путь - перебирать только его ключи и обновлять i, например так:

for i in finalschema:
    i.update({"type":'string'})
    for val in i.keys():
        if i[val] == 'attr':
            i['fields'] = finalschemanested

это, однако, модифицирует dict при повторении, и это не очень хорошая идея. Если есть лучший способ сделать то, что вы хотите, лучше подумайте о рефакторинге.

В вашем случае вам вообще не нужно перебирать i и изменять код на что-то вроде этого:

for i in finalschema:
    i["type"] = 'string'
    if i['name'] == 'attr':
        i['fields'] = finalschemanested

Кстати, вы делаете код, склонный к падению в python: i.update({'fields': finalschemanested}) будет помещать один и тот же объект finalschemanested в каждый диктовку, которую вы обновляете. Если вы выполняете эту операцию более одного раза, у вас есть один и тот же точный объект в двух разных местах, то есть изменение одного места приведет к (вероятно, нежелательному) изменению в другом месте (ах). Рассмотрите возможность использования модуля copy:

from copy import deepcopy
... 
       i.update({'fields': deepcopy(finalschemanested)})
...
...