Самый быстрый способ объединения (при сохранении значений) нескольких словарей в Python? - PullRequest
0 голосов
/ 02 октября 2018

Я гуглил по слиянию словарей, но результаты, на которые я смотрел, предполагали замену значения.То есть, если вы диктуете, как {'config_prop': 2}, а другое, как {'config_prop': 7}, конечный результат слияния будет {'config_prop': 7}.Я хочу {'config_prop': 9}.

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

split_output = [{'some_prop': 1}, {'some_prop': 2, 'other_prop': 19}]
combined_output = {}
    for d in split_output:
        if combined_output == {}:
            combined_output = d.copy()
        else:
            for key, value in d.items():
                if key in combined_output:
                    combined_output[key] = combined_output[key] + value  # add to existing val
                else:
                    combined_output[key] = value

Я хотел бы услышать предложения о лучшем способе сделатьэтот.Спасибо!

Обновление: я пробовал это, но это значительно медленнее, чем мой исходный код:

final_count = Counter() 
for d in split_output:
    final_count += Counter(d)   
final_output = dict(final_count)

Ответы [ 3 ]

0 голосов
/ 02 октября 2018

Можно использовать словарь для понимания

combo = [{'some_prop': 1}, {'some_prop': 2, 'other_prop': 19}]

d = {k: sum([i[k] for i in combo]) if k in combo[0] else i[k] for i in combo for k in i}
{'some_prop': 3, 'other_prop': 19}
0 голосов
/ 02 октября 2018

Я быстро профилировал несколько разных подходов к вашему вопросу:

combined_output = [{'some_prop': 1}, {'some_prop': 2, 'other_prop': 19}]

# set key or append value to new dictionary object:

def dict_sum(dicts):
    output = {}
    for d in dicts:
        for key, value in d.iteritems():
            if key in output:
                output[key] += value
            else:
                output[key] = value
        return output

# Implement a reducer function using functools:

from functools import reduce

def reducer(accumulator, element):
    for key, value in element.items():
        accumulator[key] = accumulator.get(key, 0) + value
    return accumulator

# Use a Counter:

from collections import Counter

def sum_dicts_values_by_key(dicts):
    return dict(sum([Counter(x) for x in combined_output], Counter()))

# Using dictionary comprehension:

def sum_dict_comprehension(dicts):
    return {k: sum([i[k] for i in dicts]) 
    if k in dicts[0] else i[k] for i in dicts for k in i}

Использование timeit для запуска быстрых тестов для сравнения:

res_1 = dict_sum(combined_output)
1000000 loops, best of 3: 457 ns per loop

res_2 = reduce(reducer, combined_output, {})
1000000 loops, best of 3: 1.35 µs per loop

res_3 = sum_dicts_values_by_key(combined_output)
100000 loops, best of 3: 12.8 µs per loop

res_4 = sum_dict_comprehension(combined_output)
1000000 loops, best of 3: 1.53 µs per loop
0 голосов
/ 02 октября 2018

Вы можете использовать следующее:

from collections import Counter

A = Counter({'config_prop': 2})
B = Counter({'config_prop': 7})
A + B
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...