Python - объединить / обновить словарь на меньшее значение - PullRequest
0 голосов
/ 09 июля 2020

Я хотел бы объединить или обновить словарь в Python новыми записями, но заменить значения записей, ключ которых существует, меньшим из значений, связанных с ключом в существующей записи и новой записи. Например:

Ввод:

dict_A = {1:14, 2:15, 3:16, 4:17}, dict_B= {2:19, 3:9, 4:11, 5:13}

Ожидаемый результат:

{1:14, 2:15, 3:9, 4:11, 5:13}

Я знаю, что это может быть достигнуто с помощью al oop итераций по словарям при выполнении сравнений , но есть ли более простые и быстрые способы или полезные библиотеки для достижения этой цели?

Ответы [ 4 ]

1 голос
/ 09 июля 2020

Быстрый однострочный

c = {**a, **b, **{key:min(a[key], b[key]) for key in set(a).intersection(set(b))} }

Объяснение

Это должно быть достаточно быстро, потому что он использует set.

Вы можете объединять словари используя синтаксис **dictionary, например: {**a, **b}. ** просто «расширяет» словарь в каждый отдельный элемент, причем последний расширенный словарь перезаписывает все предыдущие (так, в {**a, **b}, любые совпадающие ключи в b перезаписывают значение из a).


Первое, что я делаю, это загружаю все значения в a и b в новый словарь:

c = {**a, **b, ...

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

... {key:min(a[key], b[key]) for key in set(a).intersection(set(b))} ...

Чтобы получить набор ключей, которые существуют только в a и b, я конвертирую оба словаря в set s (что преобразует их в наборы их ключей) и использую intersection, чтобы быстро найти все ключи, которые есть в обоих наборах.

... set(a).intersection(set(b)) ...

Затем я oop через каждый из ключей в наборе совпадающих ключей и использовать понимание словаря для создания нового словаря с текущим key и min значений обоих словарей для этого key.

... {key:min(a[key], b[key]) ...

Чт Common crawl ru Я использую синтаксис **, чтобы «расширить» этот новый сгенерированный словарь расширенными a и b, помещая его последним, чтобы убедиться, что он перезаписывает любые значения из двух.

Работает на приведен пример (ctrl-cv'd прямо с моего терминала):

>>> a = {1:14, 2:15, 3:16, 4:17}
>>> b = {2:19, 3:9, 4:11, 5:13}
>>> c = {**a, **b, **{key:min(a[key], b[key]) for key in set(a).intersection(set(b))} }
>>> c
{1: 14, 2: 15, 3: 9, 4: 11, 5: 13}
1 голос
/ 09 июля 2020

в этом случае вы можете легко использовать pandas, чтобы не писать l oop, хотя я не знаю, будет ли какое-либо ускорение - не проверял это

import pandas as pd
df = pd.DataFrame([dict_A, dict_B])
out =  df.min().to_dict()

вывод: {1: 14.0, 2: 15.0, 3: 9.0, 4: 11.0, 5: 13.0}

есть, вероятно, некоторые крайние случаи, которые вам придется учитывать

0 голосов
/ 09 июля 2020

привет, это код, который я написал. Надеюсь, это то, что вам нужно:

dict_A = {1:14, 2:15, 3:16, 4:17}
dict_B= {2:19, 3:9, 4:11, 5:13}
dict_res =dict_B

dict_A_keys = dict_A.keys()
dict_B_keys = dict_B.keys()

for e in dict_A_keys :
    if e in dict_B_keys :
        if dict_A[e]>dict_B[e]:
            dict_res[e]=dict_B[e]
        else:
            dict_res[e]=dict_A[e]
    else:
        dict_res[e]=dict_A[e]

Я протестировал его, и результат:

{1: 14, 2: 15, 3: 9, 4: 11, 5: 13}
0 голосов
/ 09 июля 2020

Вот кое-что, чтобы сделать это. По сути, это не самый быстрый или лучший способ сделать это, но я решил, что все равно поделюсь им.

max_val = max(max(dict_A.values()), max(dict_B.values())) + 1 
keys = set(list(dict_A.keys()) + list(dict_B.keys()))
dict_C = { key : min(dict_A.get(key, max_val), dict_B.get(key, max_val)) for key in keys }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...