2013-07-25 4 views
1

К примеру у меня есть два dicts:Как слияние с добавлением двух вложенных словарей в python?

schema = { 
    'type': 'object', 
    'properties': { 
     'reseller_name': { 
      'type': 'string', 
     }, 
     'timestamp': { 
      'type': 'integer', 
     }, 
    }, 
    'required': ['reseller_name', 'timestamp'], 
} 

и

schema_add = { 
    'properties': { 
     'user_login': { 
      'type': 'string', 
     }, 
    }, 
    'required': ['user_login'], 
} 

Как я могу получить следующий слилась с добавлением результата Dict:

schema_result = { 
    'type': 'object', 
    'properties': { 
     'reseller_name': { 
      'type': 'string', 
     }, 
     'timestamp': { 
      'type': 'integer', 
     }, 
     'user_login': { 
      'type': 'string', 
     }, 
    }, 
    'required': ['reseller_name', 'timestamp', 'user_login'], 
} 

Правила:

Тот же путь properties и required для scheme и scheme_add в примере.

  1. Если оба диктата имеют один и тот же путь, они сливаются с одними и теми же правилами.
  2. Если оба файла имеют списки с одинаковым путем, добавьте первый список со вторым.
  3. Если оба dict имеют простые значения (или dict и non dict или list и non list) с тем же путем, тогда первое значение переопределяет второе.
  4. Если только один ключ имеет ключ с некоторым путем, чем установка этого ключа и значения.
+0

Вы, кажется, ответили на свой вопрос. Правила, перечисленные вами *, - это * ваш ответ. У вас проблемы с этим? Если да, то какая у вас проблема? –

+0

Мне показалось сложным, прежде чем я перечислил правила. Теперь с помощью @ Nicolas78 помогите мне это сделать. – tbicr

ответ

2

Не уверен, где проблема, но способ, которым вы ее записываете, почти как компьютерная программа, и пример подобен тестовому примеру. Почему бы вам не начать с этого?

def add_dict(d1, d2): 
    newdict = {} 
    for (key, value) in d1.iteritems(): 
     if key in d2: ... 
      #apply rules, add to newdict, use 
     else: 
      #simply add 
    for (key, value) in d2.iteritems(): 
     if not key in d1: 
      # simply add 
    return newdict 

Это, вероятно, может быть написано более плотно, но может быть проще для редактирования.

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

def merge_values(a,b): 
    if a==None or b==None: 
     return a or b 
    # now handle cases where both have values 
    if type(a)==dict: 
     return add_dict(a, b) 
    if type(a)==list: 
     ... 

def add_dict(d1,d2): 
    return dict(
     [ 
      (key, 
      merge_values(
       d1.get(key,None), 
       d2.get(key,None))) 
      for key 
      in set(d1.keys()).union(d2.keys()) 
     ]) 
2

Мое собственное решение с @ Nicolas78 помощь:

def merge(obj_1, obj_2): 
    if type(obj_1) == dict and type(obj_2) == dict: 
     result = {} 
     for key, value in obj_1.iteritems(): 
      if key not in obj_2: 
       result[key] = value 
      else: 
       result[key] = merge(value, obj_2[key]) 
     for key, value in obj_2.iteritems(): 
      if key not in obj_1: 
       result[key] = value 
     return result 
    if type(obj_1) == list and type(obj_2) == list: 
     return obj_1 + obj_2 
    return obj_2 
+2

Если вы установите 'result = dict (obj_2)', вы можете удалить весь цикл while. – RussW

+1

'result = obj_2.copy()' более быстро – tbicr

+0

А, я только заметил, что вы - вопросник. – RussW

2

Я добавляю простой решение этой проблемы. Предполагая, что данные образца не будут изменены.

def merge_nested_dicts(schema,schema_add): 
    new_schema = schema 
    for k in schema: 
     if k in schema_add.keys(): 
      if isinstance(schema_add[k],dict): 
       new_schema[k].update(schema_add[k]) 
      if isinstance(schema_add[k],list): 
       new_schema[k] = new_schema[k]+schema_add[k] 
    return new_schema 
0

Попробуйте это, если вы точно знаете ключи.

schema['properties'].update(schema_add['properties']) 
schema['result'].append(schema_add['result']) 

результат объединен в схему.

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

for value in schema: 
    if value is dict: 
     if schema_add.has_key(value) and schema_add[value] is dict: 
      schema[value].update(schema_add[value]) 
    elif value is list: 
     if schema_add.has_key(value) and schema_add[value] is list: 
      schema[value].append(schema_add[value]) 

Результат может быть объединен в другой dict.

Смежные вопросы