Python 如何递归地遍历两个字典,并基于另一个字典修改原始字典?
我正在尝试遍历一个字典(它有许多字符串、dict、dict列表),并将其与另一个字典进行比较 下面是一个例子:Python 如何递归地遍历两个字典,并基于另一个字典修改原始字典?,python,algorithm,dictionary,recursion,Python,Algorithm,Dictionary,Recursion,我正在尝试遍历一个字典(它有许多字符串、dict、dict列表),并将其与另一个字典进行比较 下面是一个例子: data = { "topic": "Seniors' Health Care Freedom Act of 2007", "foo": "bar", "last_update": "2011-08-29T20:47:44Z", "organ
data = {
"topic": "Seniors' Health Care Freedom Act of 2007",
"foo": "bar",
"last_update": "2011-08-29T20:47:44Z",
"organisations": [
{
"organization_id": "22973",
"name": "National Health Federation",
"bar": "baz"
},
{
"organization_id": "27059",
"name": "A Christian Perspective on Health Issues"
},
]}
validate = {
"topic": None,
"last_update": "next_update",
"organisations": [
{
"organization_id": None,
"name": None
}
]
}
基本上,如果项目存在于“数据”中,但在当前点不存在于“验证”中,则应将其从数据中删除
因此,在本例中,我希望数据[“foo”]和数据[“organizations”][x][“bar”]从数据目录中删除
此外,如果validate中的键有一个字符串值并且不是“None”,我想将数据中的键名更新为该值,即“last_update”应该变成“next_update”
我不确定在Python中有什么好方法可以做到这一点,我当前的版本删除了“foo”,但我正在努力删除嵌套键,比如[x][bar]
这是我目前的尝试:
def func1(data, validate, parent = None):
for k, v in sorted(data.items()):
if not parent:
if k not in validate:
data.pop(k, None)
if isinstance(v, dict):
func1(v, validate)
elif isinstance(v, list):
for val in v:
func1(val, validate, parent = k)
func1(data, validate)
我尝试使用类似这样的方法来比较键,但我认为如果数据中有额外的键(似乎删除了错误的键),则效果不好,因为dict是未排序的,因此对我没有用处:
for (k, v), (k2, v2) in zip(sorted(data.items()), sorted(validate.items())):
我读过类似的文章,比如,但这似乎使用了一个平面集进行过滤,因此它没有考虑到dict中键的位置,这对我来说很重要,因为“last_update”可以出现在我需要保留它的其他列表中。这里是一个简单的递归函数。嗯,过去很简单,;然后我添加了大量的检查,现在这是一个if森林
def验证数据(数据,验证):
对于输入列表(data.keys()):
如果密钥不在验证中:
del数据[键]
elif validate[key]不是无:
如果存在(数据[键],dict):
验证数据(数据[键]、验证[键])
elif isinstance(数据[键],列表):
对于子数据,在zip中进行子验证(数据[key],验证[key]):
如果isinstance(子数据,dict)和isinstance(子验证,dict):
验证数据(子数据,子验证)
其他:
数据[键]=验证[键]
它的工作原理:如果data[key]
是一个字典,并且key
是有效的,那么我们要对照data[key]
中的键检查data[key]
中的键。所以我们做了一个递归调用,但不是在递归调用中放入validate
,而是放入validate[key]
。同样,如果数据[key]
是一个列表
假设:如果data
中的一个列表包含非字典的元素,或者当data[key]
存在但不是字典或无字典时data[key]
是字典,或者当validate[key]存在时data[key]
是列表,则上述代码将失败
存在,但不是列表或无
关于if林的重要注意事项:if/else/if/elif/else的顺序很重要。特别是,我们只在没有列表的情况下执行data[key]=validate[key]
。如果validate[key]
是一个列表,那么data[key]=validate[key]
将导致data[key]
成为同一个列表,而不是列表的副本,这肯定不是您想要的
关于
列表(data.keys())
的重要注意事项:我使用迭代作为输入列表(data.keys()):
而不是作为输入数据:
或作为输入键,数据中的值:
。通常这不是迭代dict的首选方式。但是我们在for循环中使用del
从字典中删除值,这会干扰迭代。因此,我们需要在删除任何元素之前获得键列表,然后使用该列表进行迭代。有趣的问题!为了防止大量的if…else…
,您需要找到一种允许递归的方法,而不管传入值的类型如何
因此,我认为您需要以下规则:
数据
中的任何值在验证
中为无,则应保留数据
中的值数据
和验证
中的值是字典,则仅保留数据
中的键(如果也存在于验证
中),并将这些规则递归应用于其他键数据
和验证
中的值是列表,则仅保留数据
中的项目(如果也存在于验证
中),并将这些规则递归应用于其他项目数据
中的任何值在验证
中不为无且规则(2)和(3)不适用,则数据
中的值应替换为验证
>清理(数据、验证)
{
“主题”:2007年《老年人保健自由法》,
“上次更新”:“下次更新”,
‘机构’:[
{
“组织id”:“22973”,
“名称”:“国家卫生联盟”
}
]
}
根据规则3,我假设如果validate
中不存在,您希望从data
中删除所有列表项,因此删除第二个I