我有一个嵌套的字典,其中包含父母(键)和他们的孩子(值)。如果父级是树中另一个父级的子级,我想删除父级及其子级,即,如果键在字典中的其他位置作为值出现,我想删除它。这是示例输入/输出:
输入:
{
"Animal": {
"Cat": [],
"Dog": {
"Labrador": {
"LabradorPup": []
}
}
},
"DieselCar": {
"Hyundai": []
},
"Dog": {
"Labrador": {
"LabradorPup": []
}
},
"ElectricCar": {
"Tesla": []
},
"Labrador": {
"LabradorPup": []
},
"PetrolCar": {
"Ford": [],
"Hyundai": []
},
"Vehicle": {
"DieselCar": {
"Hyundai": []
},
"ElectricCar": {
"Tesla": []
},
"PetrolCar": {
"Ford": [],
"Hyundai": []
}
}
}
所需的输出:
{
"Animal": {
"Cat": [],
"Dog": {
"Labrador": {
"LabradorPup": []
}
}
},
"Vehicle": {
"DieselCar": {
"Hyundai": []
},
"ElectricCar": {
"Tesla": []
},
"PetrolCar": {
"Ford": [],
"Hyundai": []
}
}
}
我有以下代码保留有孩子的父母,但这不会产生我想要的输出:
inheritance_tree = {parent:children for parent, children in inheritance_tree.items() if any(child for child in children.values())}
您可以看到"Dog"
密钥虽然是"Animal"
的子代,但并未删除:
{
"Animal": {
"Cat": [],
"Dog": {
"Labrador": {
"LabradorPup": []
}
}
},
"Dog": {
"Labrador": {
"LabradorPup": []
}
},
"Vehicle": {
"DieselCar": {
"Hyundai": []
},
"ElectricCar": {
"Tesla": []
},
"PetrolCar": {
"Ford": [],
"Hyundai": []
}
}
}
答案 0 :(得分:1)
我认为any(child for child in children.values())
不是确定children
是否应保留在最终决定中的有效方法。该表达式基本上等于“此字典是否至少有一个不是空字符串的值?”。 Dog dict有一个非空子,因此保留在您的最终dict中。
这是我要使用的方法。编写一个函数,该函数以递归方式遍历嵌套的数据结构并产生所有键,无论它们嵌套的深度如何。在每个顶级键值对上运行此函数,以标识所有子值的名称。然后创建一个新的字典,从顶层将这些名称排除在外。
def iter_all_keys(obj):
if not isinstance(obj, dict):
return
for key, value in obj.items():
yield key
for x in iter_all_keys(value):
yield x
d = {
"Animal": {
"Cat": [],
"Dog": {
"Labrador": {
"LabradorPup": []
}
}
},
"DieselCar": {
"Hyundai": []
},
"Dog": {
"Labrador": {
"LabradorPup": []
}
},
"ElectricCar": {
"Tesla": []
},
"Labrador": {
"LabradorPup": []
},
"PetrolCar": {
"Ford": [],
"Hyundai": []
},
"Vehicle": {
"DieselCar": {
"Hyundai": []
},
"ElectricCar": {
"Tesla": []
},
"PetrolCar": {
"Ford": [],
"Hyundai": []
}
}
}
child_names = {child_name for toplevel_name, toplevel_children in d.items() for child_name in iter_all_keys(toplevel_children)}
d = {key: value for key, value in d.items() if key not in child_names}
print(d)
结果(为清楚起见,我添加了空格)
{
'Animal': {
'Dog': {
'Labrador': {
'LabradorPup': []
}
},
'Cat': []
},
'Vehicle': {
'DieselCar': {
'Hyundai': []
},
'PetrolCar': {
'Hyundai': [],
'Ford': []
},
'ElectricCar': {
'Tesla': []
}
}
}
请注意,这只会从顶层删除重复项。如果要在这样的字典上运行此代码:
d = {
"Human":{
"Fred": [],
"Barney": []
},
"Caveman":{
"Fred": [],
"Barney": []
}
}
...然后,结果字典将与输入相同。 Fred和Barney在数据结构中都出现两次。如果这不是期望的结果,则不清楚结果应该是什么。应当从人类还是穴居人中移除弗雷德和巴尼?如果逻辑应该是“保持Fred和Barney in Human,因为这是我们首先遇到的逻辑。请摆脱其余的逻辑”,那么结果将不是确定性的,因为不能保证2.7中的字典是有序的。
答案 1 :(得分:1)
inheritance_tree = {
parent:children for parent, children in inheritance_tree.items() if any(
child for child in children.values()
)
}
任何人都要检查孩子是否有自己的孩子。 因此,您当前的代码所做的只是保留有孙子的父母。 如果要从列表中删除这些子级,可以编写一个遍历列表的函数,并修改其副本。
如果您希望坚持使用一根衬纸,则需要在继承树的值中查找父项。 但是,这些值可能不同于字典,因此您也需要检查该值。
y= {parent:children for parent, children in x.items() if all(
[(parent not in set(k.keys())) for k in x.values() if k])
}
答案 2 :(得分:0)
尝试一下:
我知道它很复杂。
aa = [i for i,j in a.items()]
bb = [get_all_keys(j) for i,j in a.items()]
for i in aa:
for j in bb:
if i in j:
for k in a:
if k==i:
del a[k]
告诉我你是对还是错。