python-3.x - python - 将两个或更多的字典合并为相同的键

我有两个字典"i"和"iu_items "


items = {"A": 1, "B": 2, "C": 3}



u_items = {"D": 4, "B": 4, "E": 8, "C": 4}



我想用u_items更新items词典,所以,我做了这个,


items.update((k + '_1' if k in items else k, v) for k, v in u_items.items())



这样我可以区分两个字典中的键

输出:


items = {'A': 1, 'B': 2, 'C': 3, 'D': 4, 'B_1': 4, 'E': 8, 'C_1': 4}



但是,当我用另一字典更新项目字典时,让我们假设n_items代替了B_1,而不是使它成为B_1_1,


n_items = {"C":7, "B":9}



items.update((k + '_1' if k in items else k, v) for k, v in n_items.items())



输出:


{'A': 1, 'B': 2, 'C': 3, 'D': 4, 'B_1': 9, 'E': 8, 'C_1': 7}



但是,我希望输出如下所示:


{'A': 1, 'B': 2, 'C': 3, 'D': 4, 'B_1': 4, 'E': 8, 'C_1': 4, 'B_1_1':9,'C_1_1':7}



或者像这样:


{'A': 1, 'B': 2, 'C': 3, 'D': 4, 'B_1': 4, 'E': 8, 'C_1': 4, 'B_2':9,'C_2':7}



我怎么做?

时间:

虽然这看起来有点像XY问题,但是这是一个不优雅的(而且我很确定),并不是一般的解决方案:

合并字典,通过将"_1 "附加到现有key(在一行中执行所有操作),按照您的要求,那么我建议(因为有些情况下最短的不是一定是最好的),

  • 使用函数(避免重复代码(表达式))
  • 子类化dict,并重写它更新方法(上一个更好的变体),

>>> items = {"A": 1, "B": 2, "C": 3}


>>> u_items = {"D": 4, "B": 4, "E": 8, "C": 4}


>>> n_items = {"C": 7, "B": 9}


>>>


>>> items.update((max([k1 + "_1" for k1 in items if k1 == k or k1.startswith(k + "_1")], key=lambda x:len(x), default=k), v) for k, v in u_items.items())


>>> items


{'A': 1, 'B': 2, 'C': 3, 'D': 4, 'B_1': 4, 'E': 8, 'C_1': 4}


>>>


>>> items.update((max([k1 + "_1" for k1 in items if k1 == k or k1.startswith(k + "_1")], key=lambda x:len(x), default=k), v) for k, v in n_items.items())


>>> items


{'A': 1, 'B': 2, 'C': 3, 'D': 4, 'B_1': 4, 'E': 8, 'C_1': 4, 'C_1_1': 7, 'B_1_1': 9}


>>>


>>>


>>> # Merging an additional dictionary


...


>>> v_items = {"C": 25}


>>>


>>> items.update((max([k1 + "_1" for k1 in items if k1 == k or k1.startswith(k + "_1")], key=lambda x:len(x), default=k), v) for k, v in v_items.items())


>>> items


{'A': 1, 'B': 2, 'C': 3, 'D': 4, 'B_1': 4, 'E': 8, 'C_1': 4, 'C_1_1': 7, 'B_1_1': 9, 'C_1_1_1': 25}



你可以迭代地执行这个操作:


def combine(*args):


 result = {}


 for d in args:


 for key, value in d.items():


 key = str(key)


 while key in result:


 key += '_1'


 result[key] = value



 return result



print(combine(items, u_items, n_items))



输出:


{'A': 1,


 'B': 2,


 'C': 3,


 'D': 4,


 'B_1': 4,


 'E': 8,


 'C_1': 4,


 'C_1_1': 7,


 'B_1_1': 9}



使用operator.itemgetter


items = {'A':1, 'B':2, 'C':3}


u_items = {'D':4, 'B':4, 'E':8, 'C':4}


n_items = {"C":7, "B":9}



def update_dict(d1, d2):


 l = list(map(itemgetter(0), d1))


 d1.update(('_'.join([k,str(l.count(k))]) if k in l else k, v) 


 for k,v in d2.items())



update_dict(items, u_items)


update_dict(items, n_items)



使用u_items在第一次更新时输出:


{'A': 1, 'B': 2, 'B_1': 4, 'C': 3, 'C_1': 4, 'D': 4, 'E': 8}



使用n_items在第二个更新时输出:


{'A': 1,


 'B': 2,


 'B_1': 4,


 'B_2': 9,


 'C': 3,


 'C_1': 4,


 'C_2': 7,


 'D': 4,


 'E': 8}



你可以使用一个小的helper函数:


d1 = {'A':1, 'B':2, 'B_1':3, 'B_1_1':4}


d2 = {'A':1, 'B':2}



def gen_key(key, dct):


 while key in dct:


 key += '_1'


 return key



d1.update((gen_key(k, d1), v) for k, v in d2.items())



print(d1)


# {'A': 1, 'B': 2, 'B_1': 3, 'B_1_1': 4, 'A_1': 1, 'B_1_1_1': 2}



...