如果键作为值出现在其他地方,则从嵌套字典中删除它们

2024-10-06 15:25:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个嵌套字典,其中包含父级(键)和子级(值)。如果父项是树中另一个父项的子项,我想删除父项及其子项,也就是说,如果某个键作为值出现在字典的其他地方,我想删除它。以下是输入/输出示例:

输入:

{
    "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":  []
        }
    }
}

Tags: catchildrendogvehicle子项fordanimaltesla
3条回答
inheritance_tree = {
parent:children for parent, children in inheritance_tree.items() if any(
    child for child in children.values()
    )
}

检查孩子们是否有自己的孩子。 所以你现在的代码只保留有孙子的父母。 如果希望从列表中删除这些子级,可以编写一个函数遍历该列表,并修改其副本。你知道吗

如果您希望使用单行程序,那么需要在继承树的值中查找父级。 但是,这些值可能不同于dict,因此您也需要检查它。你知道吗

y= {parent:children for parent, children in x.items() if all(
[(parent not in set(k.keys())) for k in x.values() if k])
}

我不认为any(child for child in children.values())是确定children是否应该保留在最终dict中的有效方法。这个表达式基本上等同于“这个dict是否至少有一个值不是空字符串?”。狗的dict有一个非空的孩子,所以它保留在你的最终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": []
    }
}

。。。结果dict将与输入相同。弗雷德和巴尼在数据结构中都出现过两次。如果这不是期望的结果,那么不清楚结果应该是什么。弗雷德和巴尼应该从人类还是穴居人身上除名?如果逻辑应该是“把弗雷德和巴尼留在人里面,因为那是我们第一次遇到的。去掉剩下的”,那么结果就不是确定的,因为2.7中的字典不能保证是有序的。你知道吗

试试这个:

我知道这很复杂。你知道吗

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]

告诉我你是对是错。你知道吗

相关问题 更多 >