假设我有一个名为data
的字典,如下所示:
{
001: {
'data': {
'fruit': 'apple',
'vegetable': 'spinach'
},
'text': 'lorem ipsum',
'status': 10
},
002: {
.
.
.
}
}
我想平坦(?)数据键并将其转换为:
{
001: {
'fruit': 'apple',
'vegetable': 'spinach',
'text': 'lorem ipsum',
'status': 10
},
002: {
.
.
.
}
}
我正在尝试使用字典推导来实现这一点。下面是for循环的实现:
mydict = {}
for id, values in data.items():
mydict[id] = {}
for label, value in values.items():
if label == 'data':
for x, y in value.items():
mydict[id][x] = y
else:
mydict[id][label] = value
我尝试低于理解,但它给出了语法错误:
mydict = {
id: {x: y} for x, y in value.items() if label == 'data' else {label: value}
for id, values in data.items() for label, value in values.items()}
是否有一种方法可以只使用推导式来实现这一点?
使用字典展开:
mydict = {i:{**v['data'], **{k:u for k, u in v.items() if k != "data"}} for i, v in data.items()}
推导式(dict、list、set、generator)中的if
子句适用于迭代本身,不能用于生成。因此,您需要在生产中使用条件语句。
一般来说,推导实际上是一种特定类型(可能嵌套的)迭代的重组:
- 一堆迭代和条件,可能嵌套
- 单个追加/设置
for a in b:
if c:
for d in e:
for f in g:
if h:
thing.append(i)
可以被理解,只需将生产(i
)移动到头部并将其他位放在平面序列中:
thing = [
i
for a in b
if c
for d in e
for f in g
if h
]
现在你的理解没有意义,因为它从迭代value
开始,并且在理解过滤器中没有else
,即使我们添加双亲{x: y} for x, y in value.items()
也不是一个值。理解也不会"合并"。项,因此使用:
mydict = {
id: {label: value}
for id, values in data.items() for label, value in values.items()
}
你只会得到每个id的最后一个{label: value}
,因为这就是字典的工作方式。
如果你考虑生产循环,它是这样的:
for id, values in data.items():
mydict[id] = {}
这意味着是你的字典理解:
mydict = {
id: {}
for id, values in data.items()
}
迭代的其余部分是填充值,所以它需要在产品中有一个单独的迭代:
mydict = {
id: {
label: value ???
for label, value in values.items()
}
for id, values in data.items()
}
在这种情况下,你遇到的问题是,这并不完全工作,因为你不能&;有条件地迭代&;在推导式中,要么全有,要么全无。
除了你可以:in
的右边是一个正常表达式,所以你可以对它做任何你想做的事情,这意味着你可以展开或折叠:
mydict = {
id: {
x: y
for label, value in values.items()
for x, y in (value.items() if label == 'data' else [(label, value)])
}
for id, values in data.items()
}
在非数据的情况下,这有点昂贵,因为您需要在元组和列表中重新包装键和值,但这不太可能是一个大问题。
另一种替代方法是使用飞溅来合并两个字典(其中一个是通过comp创建的),而不是使用条件推导式:
mydict = {
id: {
**values['data'],
**{label: value for label, value in values.items() if label != 'data'}
}
for id, values in data.items()
}
这也可以应用到原文中以简化它:
mydict = {}
for id, values in data.items():
mydict[id] = {}
for label, value in values.items():
if label == 'data':
mydict[id].update(value)
else:
mydict[id][label] = value
让我简化一下;
sample_data = {
"001": {
"data": {
"fruit": 'apple',
"vegetable": 'spinach'
},
"text": 'lorem ipsum',
"status": 10
},
"002": {
"data": {
"fruit": 'apple',
"vegetable": 'spinach'
},
"text": 'lorem ipsum',
"status": 10
}
}
for key, row in sample_data.items():
if 'data' in row.keys():
info = sample_data[key].pop('data')
sample_data[key] = {**row, **info}
print(sample_data)