Свернуть вложенный dict в список dict в python - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть входной вложенный dict следующим образом:

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

Ожидаемый вывод выглядит следующим образом:

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

Мой код выглядит следующим образом:

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'}]

Работает, как и ожидалось. Однако, это работает только для python 3.5 и выше, поскольку {** x, ** y} для объединения 2 dicts было введено только из этой версии.

Кроме того, мой набор данных огромен, и я не уверен, является ли это наиболее эффективным способом для достижения этого. Каков наилучший способ для достижения этого Python 2.7.Я также открыт для использования внешних библиотек, таких как Pandas и numpy.

Ответы [ 5 ]

0 голосов
/ 20 февраля 2019

Может быть, простое понимание списка, хотя с грязным взломом, чтобы вернуть результат:

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}]
0 голосов
/ 20 февраля 2019

С питоном 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}]
0 голосов
/ 20 февраля 2019

Я бы использовал 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}]
0 голосов
/ 20 февраля 2019

в 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)
0 голосов
/ 20 февраля 2019

Вот решение с использованием 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'))

Вывод:

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

PS: протестировано на python3, но должно работать и на python2.7 *

Редактировать

Более общее решение с дополнительным ключом Теперь вам не нужно жестко кодировать другие ключи.

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'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...