简体   繁体   English

将嵌套字典折叠到python中的字典列表中

[英]Collapse a nested dict into a list of dicts in python

I have an input nested dict as follows: 我有一个输入嵌套字典,如下所示:

{'name': 'Mark', 'marks':[{'english':20, 'maths':25},{'english':50, 'maths':55}]}

The output i am expecting is as follows: 我期望的输出如下:

[{'name': 'Mark', 'english':23, 'maths':35}, {{'name': 'Mark', 'english':50, 'maths':55}]

My code is as follows: 我的代码如下:

In [22]: input = {'name': 'Mark', 'marks':[{'english':20, 'maths':25},{'english':50, 'maths':55}]}

In [23]: marks = input.pop('marks')

In [24]: output = []

In [25]: for mark in marks:
    ...:     output.append({**input, **mark})
...:

In [26]: output
Out[26]:
[{'english': 20, 'maths': 25, 'name': 'Mark'},
 {'english': 50, 'maths': 55, 'name': 'Mark'}]

Works as expected.However, this works only for python 3.5 and above since {**x, **y} to merge 2 dicts was only introduced from that version on. 可以正常工作。但是,这仅适用于python 3.5及更高版本,因为{** x,** y}仅合并了该版本的2份字典。

Also my dataset is huge and I am not sure if this is the most efficient way to achieve this.What is the is best way to achieve this python 2.7. 另外我的数据集很大,我不确定这是否是实现此目标的最有效方法,什么是实现此python 2.7的最佳方法? I am also open to using external libraries like Pandas and numpy . 我也愿意使用外部库,例如Pandasnumpy

Here's solution using pandas : 这是使用pandas的解决方案:

import pandas as pd

x = {'name': 'Mark', 'marks':[{'english':20, 'maths':25},{'english':50, 'maths':55}]}

x = pd.DataFrame(x)
x = pd.concat([x['name'],x['marks'].apply(pd.Series)], axis=1)

print(x.to_dict(orient='records'))

Output: 输出:

[{'english': 20, 'name': 'Mark', 'maths': 25}, 
 {'english': 50, 'name': 'Mark', 'maths': 55}]  

PS: tested on python3 but it should work on python2.7 as well PS:在python3上测试过,但它也应该在python2.7上工作

Edit 编辑

More generic solution with additional key Now you don't have to hardcode the other keys. 带有附加密钥的更通用的解决方案现在,您不必对其他密钥进行硬编码。

x = {'name': 'Mark', 'add':'Mum','marks':[{'english':20, 'maths':25},{'english':50, 'maths':55}]}


x = pd.DataFrame(x)
cols = list(x.columns)  
cols.remove('marks')  # to get columns except `mark`

x = pd.concat([x[cols],x['marks'].apply(pd.Series)], axis=1)
print(x.to_dict(orient='records'))

Maybe simple list comprehension though with dirty hack to return the result: 也许是简单的列表理解,但是会返回结果:

input = {'name': 'Mark', 'marks':[{'english':20, 'maths':25},{'english':50, 'maths':55}]}

marks_list = input.pop('marks')
output = [marks.update(input) or marks for marks in marks_list]

[{'name': 'Mark', 'maths': 25, 'english': 20}, {'name': 'Mark', 'maths': 55, 'english': 50}]

I would use pydash ( https://pydash.readthedocs.io/en/latest/ ), it supports python 2.7: 我会使用pydash( https://pydash.readthedocs.io/en/latest/ ),它支持python 2.7:

from pydash import py_ as _
inputs = {'name': 'Mark', 'marks':[{'english':20, 'maths':25},{'english':50, 'maths':55}]}

def construct_dict(d1, d2):
   d1.update(d2)
   return d1

_(inputs['marks']).map(lambda x: construct_dict({ 'name': inputs['name'] }, x)).value()

# output
[{'maths': 25, 'name': 'Mark', 'english': 20}, {'maths': 55, 'name': 'Mark', 'english': 50}]

in python2.7 i would do the following: 在python2.7中,我将执行以下操作:

input = {'name': 'Mark', 'marks':[{'english':20, 'maths':25},{'english':50, 'maths':55}]}

marks = input.pop('marks')
output =  map(lambda x:dict(input, **x), marks)

With python 2.7: 使用python 2.7:

idict =  {'name': 'Mark', 'marks':[{'english':20, 'maths':25},{'english':50, 'maths':55}]}
print (idict)
marks = idict.pop("marks")
result = []
for each in marks:
    result.append({'name': idict['name']})
    for key, val in each.items():
        result[-1][key] = val
print (result)

{'name': 'Mark', 'marks': [{'maths': 25, 'english': 20}, {'maths': 55, 'english': 50}]}
[{'maths': 25, 'name': 'Mark', 'english': 20}, {'maths': 55, 'name': 'Mark', 'english': 50}]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM