【问题标题】:Merging 2 list of dicts based on common values根据共同值合并 2 个字典列表
【发布时间】:2016-01-20 16:36:54
【问题描述】:

所以我有 2 个字典列表,如下所示:

list1 = [
{'name':'john',
'gender':'male',
'grade': 'third'
},
{'name':'cathy',
'gender':'female',
'grade':'second'
},
]

list2 = [
{'name':'john',
'physics':95,
'chemistry':89
},
{'name':'cathy',
'physics':78,
'chemistry':69
},
]

我需要的输出列表如下:

final_list = [
{'name':'john',
'gender':'male',
'grade':'third'
'marks': {'physics':95, 'chemistry': 89}
},
{'name':'cathy',
'gender':'female'
'grade':'second'
'marks': {'physics':78, 'chemistry': 69}
},
]

首先我尝试如下迭代:

final_list = []
for item1 in list1:
    for item2 in list2:
        if item1['name'] == item2['name']:
            temp = dict(item_2)
            temp.pop('name')
            final_result.append(dict(name=item_1['name'], **temp))

但是,这并没有给我想要的结果..我也尝试过 pandas..那里的经验有限..

>>> import pandas as pd
>>> df1 = pd.DataFrame(list1)
>>> df2 = pd.DataFrame(list2)
>>> result = pd.merge(df1, df2, on=['name'])

但是,我不知道如何将数据恢复为我需要的原始格式..任何帮助

【问题讨论】:

  • 为什么凯西和凯西在一起?
  • 另外,dicts 应该是[{'physics':78, 'chemistry': 69}],带有大括号。
  • 也修复了这个问题..

标签: python list dictionary pandas


【解决方案1】:

考虑到您想要一个 dicts 列表作为输出,您可以在没有 pandas 的情况下轻松地做您想做的事情,使用 dict 使用名称作为外部键来存储所有信息,而不像 @987654321 那样遍历每个列表@你自己的代码中的双循环:

out = {d["name"]: d for d in list1}
for d in list2:
    out[d.pop("name")]["marks"] = d


from pprint import pprint as pp

pp(list(out.values()))

输出:

[{'gender': 'female',
  'grade': 'second',
  'marks': {'chemistry': 69, 'physics': 78},
  'name': 'cathy'},
 {'gender': 'male',
  'grade': 'third',
  'marks': {'chemistry': 89, 'physics': 95},
  'name': 'john'}]

如果你想创建新的字典,它会重用列表中的字典:

out = {d["name"]: d.copy() for d in list1}

for d in list2:
    k = d.pop("name")
    out[k]["marks"] = d.copy()

from pprint import pprint as pp

pp(list(out.values()))

输出是一样的:

[{'gender': 'female',
  'grade': 'second',
  'marks': {'chemistry': 69, 'physics': 78},
  'name': 'cathy'},
 {'gender': 'male',
  'grade': 'third',
  'marks': {'chemistry': 89, 'physics': 95},
  'name': 'john'}]

【讨论】:

  • @Padraic ..这很好..我想听听您的意见,因为您已经回答了我的很多问题..什么时候应该使用 pandas 或 numpy 之类的东西,什么时候应该使用使用传统方法..前者总是更快..有没有我可以遵循的经验法则..
  • @Amistad,没有一个答案,如果你真的关心性能,你会寻找 numpy 或 pandas 但这也取决于你实际想要对数据做什么,因为你想要一个 dict 我认为上面的代码将是我将使用的代码,它的优点是所有操作都使用标准库完成。我还更改了代码以仅使用常规字典
【解决方案2】:

创建一个将添加marks 列的函数,该列应包含physics 和chemistry 标记的字典

def create_marks(df):
    df['marks'] = { 'chemistry' : df['chemistry'] , 'physics' : df['physics'] }
    return df

result_with_marks = result.apply( create_marks , axis = 1)

Out[19]:
gender  grade   name    chemistry   physics            marks
male    third   john    89             95   {u'chemistry': 89, u'physics': 95}
female  second  cathy   69             78   {u'chemistry': 69, u'physics': 78}

然后将其转换为您想要的结果,如下所示

result_with_marks.drop( ['chemistry' , 'physics'], axis = 1).to_dict(orient = 'records')

Out[20]:
[{'gender': 'male',
  'grade': 'third',
  'marks': {'chemistry': 89L, 'physics': 95L},
  'name': 'john'},
 {'gender': 'female',
  'grade': 'second',
  'marks': {'chemistry': 69L, 'physics': 78L},
  'name': 'cathy'}]

【讨论】:

    【解决方案3】:

    你可以先合并两个数据框

    In [144]: df = pd.DataFrame(list1).merge(pd.DataFrame(list2))
    

    看起来像,

    In [145]: df
    Out[145]:
       gender   grade   name  chemistry  physics
    0    male   third   john         89       95
    1  female  second  cathy         69       78
    

    然后创建一个标记列作为字典

    In [146]: df['marks'] = df.apply(lambda x: [x[['chemistry', 'physics']].to_dict()], axis=1)
    
    In [147]: df
    Out[147]:
       gender   grade   name  chemistry  physics  \
    0    male   third   john         89       95
    1  female  second  cathy         69       78
    
                                      marks
    0  [{u'chemistry': 89, u'physics': 95}]
    1  [{u'chemistry': 69, u'physics': 78}]
    

    并且,使用 to_dict(orient='records') 数据框选定列的方法

    In [148]: df[['name', 'gender', 'grade', 'marks']].to_dict(orient='records')
    Out[148]:
    [{'gender': 'male',
      'grade': 'third',
      'marks': [{'chemistry': 89L, 'physics': 95L}],
      'name': 'john'},
     {'gender': 'female',
      'grade': 'second',
      'marks': [{'chemistry': 69L, 'physics': 78L}],
      'name': 'cathy'}]
    

    【讨论】:

    • 就像一个魅力..最后一件事..附加到整数值末尾的“L”是什么,我该如何避免它们..
    • 使用x[['chemistry', 'physics']].astype(int).to_dict() 或astype(float)?
    【解决方案4】:

    使用您的 pandas 方法,您可以调用

    result.to_dict(orient='records')
    

    将其作为字典列表取回。但它不会将marks 作为子字段放入,因为没有任何东西告诉它这样做。 physics 和 chemistry 将只是与其余字段处于同一级别的字段。

    您也可能遇到问题,因为您的name 在第一个列表中是'cathy' 而在第二个列表中是'kathy',这自然不会被合并。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-17
      • 1970-01-01
      • 2022-11-28
      • 1970-01-01
      • 2023-01-26
      • 1970-01-01
      • 1970-01-01
      • 2016-02-22
      相关资源
      最近更新 更多