2015-08-14 3 views
0

Скажем, у вас есть словарь словарей, но вы хотите скопировать почти всю структуру (за исключением значений самых внутренних словарей). Следующий код может делать то, что я хочу, но я уверен, что есть более разумный способ сделать это:копировать сложную структуру словаря

import sys 

def main(argv=()): 

    # original dictionary 
    data = {1:{'l1': [1,2,3], 'l2': [2,1,6]}, 2: {'t1': ("w?",2), 't2': ("h!",4)}} 

    # new values for the innermost keys 
    newd = {'l1' : 1, 'l2' : 2, 't1' : 3, 't2' : 4} 

    copy = dict.fromkeys(data.keys(), {}) 
    for k in copy.keys(): 
     copy[k] = dict.fromkeys(data[k].keys(), None) 

    for k in copy.values(): 
     for e in k.keys(): 
      k[e] = newd[e] 

    print(data) 
    print(copy) 

if __name__ == "__main__": 
    sys.exit(main()) 

Так код выше принтами:

{1: {'l2': [2, 1, 6], 'l1': [1, 2, 3]}, 2: {'t1': ('w?', 2), 't2': ('h!', 4)}} 
{1: {'l2': 2, 'l1': 1}, 2: {'t1': 3, 't2': 4}} 

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

ответ

1

Вы можете использовать (при условии, Python 3 из вашего кода):

>>> copy = {outer_key: {inner_key: newd.get(inner_key, inner_dict[inner_key]) for inner_key in inner_dict} for outer_key,inner_dict in data.items()} 
>>> copy 
{1: {'l1': 1, 'l2': 2}, 2: {'t1': 3, 't2': 4}} 
>>> data 
{1: {'l1': [1, 2, 3], 'l2': [2, 1, 6]}, 2: {'t1': ('w?', 2), 't2': ('h!', 4)}} 

Вы можете упростить newd.get(inner_key, inner_dict[inner_key]) к newd[inner_key] если вы 100% уверены, что каждый ключи находятся в newd. Или до newd.get(inner_key), если вам все равно, что вы потеряете значения, которые не находятся в newd.

-1

Использование модуля копирования:

import copy 
data = {1:{'l1': [1,2,3], 'l2': [2,1,6]}, 2: {'t1': ("w?",2), 't2': ("h!",4)}} 
cdata = copy.deepcopy(data) 

Тогда вам придется изменить последние dicts в копии с новыми значениями.

См. Модуль копирования для глубокого и мелкого копирования.

Если вы собираетесь делать это вручную, чтобы не заполнять последний этаж, рекурсия - это способ сделать это.

Посмотрите, как работает модуль копирования, и используйте метод dict.copy() вместо того, чтобы создавать новые dicts с помощью кнопок froms().

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

+0

Пожалуйста, прочитайте мои последние комментарии по глубокому копированию. – aaragon

+0

Извините, материал про массивы numpy. Но, тем не менее, я сказал вам, что делать. Посмотрите, как работает модуль копирования, затем напишите аналогичный алгоритм, который будет учитывать ваши спецификации. Это была суть моего ответа. Кроме того, модуль копирования является гибким, и вы можете контролировать выполняемое копирование, особенно при использовании ваших собственных объектов. – Dalen

1

Используя свой собственный код, вам не нужно вызывать .keys в любом месте, и вы можете создать dicts в первом цикле:

def main(): 

    # original dictionary 
    data = {1:{'l1': [1,2,3], 'l2': [2,1,6]}, 2: {'t1': ("w?",2), 't2': ("h!",4)}} 

    # new values for the innermost keys 
    newd = {'l1' : 1, 'l2' : 2, 't1' : 3, 't2' : 4} 

    copy = dict.fromkeys(data, {}) 
    for k in copy: 
     copy[k] = {key:newd[key] for key in data[k]} 
Смежные вопросы