Добавление словарей рекурсивно в Python - PullRequest
1 голос
/ 04 января 2012

У меня есть следующие две функции, которые берут два словаря и рекурсивно добавляют их значения.

def recursive_dict_sum_helper(v1, d2, k):
    try: v2 = d2[k]
    except KeyError: return v1 #problem is here if key not found it just return value but what about rest of the keys which is in d2??

    if not v1: return v2
    # "add" two values: if they can be added with '+', then do so,
    # otherwise expect dictionaries and treat them appropriately.
    try:
        if type(v1) == list and type(v2) == list:
            v1.extend(v2)
            return list(set(v1))
        else:
            return v1 + v2
    except: return recursive_dict_sum(v1, v2)

def recursive_dict_sum(d1, d2):
    if len(d1) < len(d2):
        temp = d1
        d1 = d2
        d2 = temp
    # Recursively produce the new key-value pair for each
    # original key-value pair, and make a dict with the results.
    return dict(
        (k, recursive_dict_sum_helper(v, d2, k))
        for (k, v) in d1.items()
    )

Если я даю следующий ввод, то вывод в порядке, который я ожидаю:

a = {'abc': {'missing': 1, 'modified': 0, 'additional': 2}}
b = {'abc': {'missing': 1, 'modified': 1, 'additional': 2}}

mn = recursive_dict_sum(a, b)

output: mn = {'abc': {'missing': 2, 'modified': 1, 'additional': 4}}

но если введено:

a = {'abc': {'missing': 1, 'modified': 0, 'additional': 2}}
b = {'cde': {'missing': 1, 'modified': 1, 'additional': 2}}

output: {'abc': {'missing': 1, 'modified': 0, 'additional': 2}} #which is wrong

Если во втором словаре не найдено ни одного ключа, возвращается значение ключа из первого словаря.Таким образом, он работает с одним элементом словаря, как насчет остальных ключей во втором словаре?Как я могу обновить вышеупомянутый скрипт так, чтобы вывод был:

output: {'abc': {'missing': 1, 'modified': 0, 'additional': 2}, 'cde': {'missing': 1, 'modified': 1, 'additional': 2}}

Ответы [ 2 ]

3 голосов
/ 04 января 2012

Если я правильно понимаю, что вы хотите сделать, все это может быть достигнуто с помощью следующего кода:

def dict_sum(d1, d2):
    if d1 is None: return d2
    if d2 is None: return d1
    if isinstance(d1, list) and isinstance(d2, list):
        return list(set(d1 + d2))
    try:
        return d1 + d2
    except TypeError:
        # assume d1 and d2 are dictionaries
        keys = set(d1.iterkeys()) | set(d2.iterkeys())
        return dict((key, dict_sum(d1.get(key), d2.get(key))) for key in keys)

dict_sum(a, b) даст желаемый результат.

Просто обратите внимание, что он вызовет AttributeError, если вызывается с несовместимыми типами, такими как

dict_sum({'a': 1}, 2)

Редактировать для особой обработки списков (создать список с уникальными элементами).

2 голосов
/ 04 января 2012

Сделано в одном монстр-генераторе, как вам это нравится:)

def recursive_dict_sum(d1, d2):
    return dict((k, ((d1[k] if k in d1 else d2[k])
                       if k not in d1 or k not in d2
                      else (d1[k] + d2[k] if not isinstance(d1[k], dict)
                                        else recursive_dict_sum(d1[k], d2[k]))))
                for k in set(d1.keys() + d2.keys()))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...