Как объединить произвольное количество словарей и объединить значения с общими ключами - PullRequest
0 голосов
/ 03 мая 2020

Предположим, у вас есть следующие словари

dict1 = {'a': 'a'}
dict2 = {'a':'b', 'c':'d' , 'f':'w', 'r':' not unique' }
dict3 = {'a': 'c', 'c':'e'}
dict4 = {'a': 'd', 'c':'e', 'f':'r'}
dict5 = {'r': 'x', 'y':'only unique', 'f':'r'}

Предполагаемый результат следующий:

{'y': 'only unique', 'a': 'abcd', 'c': 'dee', 'f': 'wrr', 'r': ' not uniquex'}

Вы хотите объединить их в определенном порядке по мере их появления. Если ключ повторяется, нужно объединить результаты. Вариант использования в 10K представлений. Часто вы найдете это

Column X Column X+1
(123)

, когда число (123)

Ответы [ 2 ]

0 голосов
/ 03 мая 2020

Вы можете использовать collections.defaultdict здесь.

from collections import defaultdict
dict1 = {'a': 'a'}
dict2 = {'a':'b', 'c':'d' , 'f':'w', 'r':' not unique' }
dict3 = {'a': 'c', 'c':'e'}
dict4 = {'a': 'd', 'c':'e', 'f':'r'}
dict5 = {'r': 'x', 'y':'only unique', 'f':'r'}

def merge(*dicts):
    out=defaultdict(str)
    for d in dicts:
        for k,v in d.items():
            out[k]+=v
    return out #The return type is defaultdict if you want dict then use `return dict(out)`

merge(dict1,dict2,dict3,dict4,dict5)
# defaultdict(<class 'str'>, {'a': 'abcd', 'c': 'dee', 'f': 'wrr', 'r': ' not uniquex', 'y': 'only unique'})

#When `return dict(out)`
# {'a': 'abcd', 'c': 'dee', 'f': 'wrr', 'r': ' not uniquex', 'y': 'only unique'}
0 голосов
/ 03 мая 2020

Я попробовал это, и это работает

# helper functions
def string_comprehension(array_like,separator,separate_chars=False):

    if not isinstance(array_like,list):
        array_like = to_list(array_like)

    if separate_chars:
        result = ''.join(separator.join(map(str, x)) for x in array_like)
    else:
        result = separator.join(str(x) for x in array_like)
    return result


def to_list(var):

    a = []

    if islist(var): return var
    else: return [var]

def merge_concatenate_dicts(dict_list, separator = ''):

    def update_common_dict(local_common_keys,global_common_dict,index_list):
        for key in list(local_common_keys):
            if key in global_common_dict.keys():
                current_indices = to_list(global_common_dict.get(key))
                new_indices = sorted(list(set.union(set(current_indices),
                                set(index_list)))) 
                common_keys_dict.update( { key: new_indices} )
            else:
                common_keys_dict.update( { key: index_list} )
        return global_common_dict


    common_keys_dict = {}

    dict_combination = it.combinations(dict_list,2)

    disjoint_keys = []

    for d_combine in dict_combination:

        index_list = sorted([dict_list.index(d_combine[0]),dict_list.index(d_combine[1])])

        keys_dict1 = list(d_combine[0].keys())
        keys_dict2 = list(d_combine[1].keys())


        common_keys = set.intersection( set(keys_dict1), 
            set(keys_dict2))

        if common_keys_dict:
            all_common_keys = list(set.union(
                    common_keys,
                    set(list(common_keys_dict.keys())
                )))
        else: all_common_keys = list(common_keys)        

        all_keys = list(reduce(set.union,
            map(set,[keys_dict1, keys_dict2] )))

        disjoint_local             = [k for k in all_keys if k not in all_common_keys]
        disjoint_universe          = list(set.union(set(disjoint_local), set(disjoint_keys)))

        disjoint_keys              = [k for k in disjoint_universe if k not in all_common_keys]

        common_keys_dict = update_common_dict(local_common_keys = common_keys,
            global_common_dict = common_keys_dict, index_list = index_list  )

    merged_dicts = {}

    for k_disjoint in disjoint_keys:
        for d in dict_list:
            if k_disjoint in d:
                merged_dicts.update({k_disjoint : d.get(k_disjoint)})
                break    

    for k_common in common_keys_dict.keys():
        dict_merge_list = [d.get(k_common) for idx,d in enumerate(dict_list) if idx in common_keys_dict.get(k_common)]
        merged_val      =  string_comprehension(array_like=dict_merge_list, separator=  separator)  
        merged_dicts.update( {k_common: merged_val} )

    return merged_dicts



dict1 = {'a': 'a'}
dict2 = {'a':'b', 'c':'d' , 'f':'w', 'r':' not unique' }
dict3 = {'a': 'c', 'c':'e'}
dict4 = {'a': 'd', 'c':'e', 'f':'r'}
dict5 = {'r': 'x', 'y':'only unique', 'f':'r'}

result = merge_concatenate_dicts([dict1,dict2,dict3,dict4,dict5])

print(result)

Выход

{'y': 'only unique', 'a': 'abcd', 'c': 'dee', 'f': 'wrr', 'r': ' not uniquex'}
...