为了账号安全,请及时绑定邮箱和手机立即绑定

合并多个键不一致的字典

合并多个键不一致的字典

泛舟湖上清波郎朗 2021-11-23 19:00:37
我是一名 Python 初学者,正在努力解决以下问题:我正在尝试将多个列表与从多个 json 解码的嵌套字典合并。列表之间的共同点是每个嵌套字典的“uid”键对应于一个名称,但问题是某些字典的键名称不同。例如,代替“uid”,字典可能有“number”作为键。我想将它们的一部分合并到一个超级嵌套字典列表中。为了说明,我所拥有的是:masterlist = [ ]listA = [{"uid": "12345", "name": "John Smith"}, {etc...}]listB = [{"number": "12345", "person": "John Smith", "val1": "25"}, {etc...}]listC = [{"number": "12345", "person": "John Smith", "val2": "65"}, {etc...}]我想结束的是:masterlist = [{"uid": "12345", "name": "John Smith", "val1": "25", "val2: "65"}, {etc...}]这是否可以通过迭代和比较相同的“uid”值来有效/pythonically 完成?我已经看到很多关于通过匹配键进行合并的操作方法,但这里的问题显然是键不一致。排序无所谓。我所需要的只是让主列表包含每个 dict 条目的相应 uid、名称和值。希望这是有道理的,谢谢!
查看完整描述

3 回答

?
慕标琳琳

TA贡献1830条经验 获得超9个赞

可能有使用 base python 的解决方案,但我能想到的最简单的方法是使用 pandas 库将每个列表转换为 DataFrame,然后将它们连接/合并在一起。


import pandas as pd


dfA = pd.DataFrame(listA)

dfB = pd.DataFrame(listB)


merged_df = dfA.merge(dfB, left_on='uid', right_on='number')

这将返回一个包含比您需要的更多列的 DataFrame(即“uid”和“number”都有列),但您可以通过这种方式指定您想要的列以及您想要它们的顺序:


merged_df = merged_df[['uid', 'name', 'val1']]

要将多个 DataFrames 合并到一个主框架中,请参见此处:pandasthree -way joins multiple dataframes on columns


查看完整回答
反对 回复 2021-11-23
?
慕雪6442864

TA贡献1812条经验 获得超5个赞

您可以在没有 Pandas 的情况下使用列表推导式来完成此操作,该推导式构建字典字典,按“uid”对列表字典进行分组。然后使用该分组字典的 .values() 再次获取字典列表:


listA = [{"uid": "12345", "name": "John Smith"},{"uid": "67890", "name": "Jane Doe"}]


listB = [{"number": "12345", "person": "John Smith", "val1": "25"},{"number": "67890", "val1": "37"}]


listC = [{"number": "12345", "person": "John Smith", "val2": "65"},{"number": "67890", "val2": "53"}]


from collections import defaultdict

fn     = { "number":"uid", "person":"name" } # map to get uniform key names

data   = [ { fn.get(k,k):v for k,v in d.items() } for d in listA+listB+listC ]

result = next(r for r in [defaultdict(dict)] if [r[d["uid"]].update(d) for d in data])

print(*result.values())


{'uid': '12345', 'name': 'John Smith', 'val1': '25', 'val2': '65'} 

{'uid': '67890', 'name': 'Jane Doe', 'val1': '37', 'val2': '53'}


查看完整回答
反对 回复 2021-11-23
?
慕神8447489

TA贡献1780条经验 获得超1个赞

您应该将所有输入列表放在列表列表中,以便您可以构建一个映射uid到具有聚合项目值的 dict 的 dict,这样您所需的 dict 列表将只是映射的 dict 值。为了允许在不同的输入字典中对键的命名不一致,pop您不想要的那些(例如number和id在我的示例中)并使用您想要保留的键分配给字典(例如uid在示例中):


wanted_key = 'uid'

unwanted_keys = {'number', 'id'}

mapping = {}

for l in lists:

    for d in l:

        if wanted_key not in d:

            d[wanted_key] = d.pop(unwanted_keys.intersection(d).pop())

        mapping.setdefault(d[wanted_key], {}).update(d)

masterlist = list(mapping.values())

所以给出:


lists = [

    [

        {"uid": "12345", "name": "John Smith"},

        {"uid": "56789", "name": "Joe Brown", "val1": "1"}

    ],

    [

        {"number": "12345", "name": "John Smith", "val1": "25"},

        {"number": "56789", "name": "Joe Brown", "val2": "2"}

    ],

    [

        {"id": "12345", "name": "John Smith", "val2": "65"}

    ]

]

masterlist 变成:


[

    {'uid': '12345', 'name': 'John Smith', 'val1': '25', 'val2': '65'},

    {'uid': '56789', 'name': 'Joe Brown', 'val1': '1', 'val2': '2'}

]


查看完整回答
反对 回复 2021-11-23
  • 3 回答
  • 0 关注
  • 211 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信