Python中的嵌套字典遍历
我有一个字典,这个字典里面有一些选项的键值对,还有一个叫做sub_dict的属性,这个属性是一个包含更多字典的列表,这些字典也有相同的属性,并且它们也可能有自己的sub_dict,一直往下嵌套。
在Python中,我把这些字典拆开,逐个处理,修改它们,然后想把修改后的部分重新组合回整个字典里。不过,我不太确定该怎么遍历这些字典。
{base_system: {
name: "root",
description: "data dictionary",
common_data: {},
other_data: {},
more_data: {},
sub_systems: [
{
base_system: {
name: "another system",
description: "inherits from top level",
sub_systems: [
{
base_system: {}
},
{
base_system: {}
}
]
}
},
{
base_system: {
name: "one more system",
description: "inheriting again",
sub_systems: [
{
base_system: {
name: "child system",
description: "no kids here",
other_data: {},
more_data: {}
}
},
{
base_system: {
name: "kid system",
description: "no children here"
}
}
]
}
}
]
}
}
我想做类似的事情,但不太确定怎么让它变成递归的。
#Have some recursive function to dig through the overall dictionary then test:
if the_dict_object["space_system"]["name"] == changed_json_system["space_system"]["name"]:
#then when it passes that if statement I can just set
the_dict_object = changed_json_system
不过,我不太清楚怎么遍历这个嵌套的字典,同时又能保持对整体对象的控制。
2 个回答
1
这里有一段示例代码,它会递归地遍历你的字典结构。在这个例子中,它把描述内容替换成大写形式。
_DESC = "description"
_BASESYS = "base_system"
_SUBSYS = "sub_systems"
def uppercase_desc(system_info):
"""
Change a system object such that the description is in upper-case.
"""
if _BASESYS not in system_info:
return
subd = system_info[_BASESYS]
if _DESC in subd:
subd[_DESC] = subd[_DESC].upper()
if _SUBSYS not in subd:
return
for d in subd[_SUBSYS]:
uppercase_desc(d)
if __name__ == "__main__":
import json
with open("data.json", "rt") as f:
s = f.read()
system_info = json.loads(s)
uppercase_desc(system_info)
s = json.dumps(system_info, indent=4, sort_keys=True)
print(s)
上面的代码是在原字典上直接修改的。虽然稍微复杂一点,但其实也不难,你可以在遍历的过程中做一个副本,然后返回这个副本。这样做可能更好。
这里唯一需要注意的地方是,代码默认使用了 copy.deepcopy()
。因为我们不知道字典里可能有什么内容,而且我们想返回一个副本,所以可以对所有内容调用 copy.deepcopy()
;这样做简单有效,对于像 3
(值为3的整数)这样的简单对象也能正常工作。
import copy
_DESC = "description"
_BASESYS = "base_system"
_SUBSYS = "sub_systems"
def uppercase_desc(system_info):
"""
Change a system object such that the description is in upper-case.
"""
if _BASESYS not in system_info:
raise ValueError("only works on a system info dict")
# put in the base_system key and an empty subdir
newsubd = {}
new_system_info = {_BASESYS: newsubd}
subd = system_info[_BASESYS]
for key, value in subd.items():
if _DESC == key:
newsubd[key] = value.upper()
elif _SUBSYS == key:
newsubd[key] = [uppercase_desc(d) for d in value]
else:
newsubd[key] = copy.deepcopy(value)
return new_system_info
if __name__ == "__main__":
import json
with open("data.json", "rt") as f:
s = f.read()
system_info = json.loads(s)
new_system_info = uppercase_desc(system_info)
s = json.dumps(new_system_info, indent=4, sort_keys=True)
print(s)
附言:你发布的示例数据不是有效的JSON格式。我把它修改了一下,为键加上了双引号,并进行了格式化,使得我的测试文件 data.json
看起来更整齐。这里是修改后的内容:
{
"base_system": {
"name": "root",
"description": "data dictionary",
"more_data": {},
"common_data": {},
"sub_systems": [
{
"base_system": {
"name": "another system",
"sub_systems": [
{
"base_system": {}
},
{
"base_system": {}
}
],
"description": "inherits from top level"
}
},
{
"base_system": {
"name": "one more system",
"sub_systems": [
{
"base_system": {
"more_data": {},
"other_data": {},
"name": "child system",
"description": "no kids here"
}
},
{
"base_system": {
"name": "kid system",
"description": "no children here"
}
}
],
"description": "inheriting again"
}
}
],
"other_data": {}
}
}
1
你可以使用 instanceof() 方法来检查某个东西是不是字典。如果是的话,你就可以让你的代码去遍历这个字典。我会在这种情况下使用递归。
def read_dict(some_dictionary):
for key, value in some_dictionary:
if isinstance(value, dict):
# if value is another dict, iterate through the key,value pairs in value
read_dict(value)
elif isinstance(value, list):
# if value is a list, add your own code to iterate through a list
pass
else:
#not a dict, do what you needed to do eg:
print 'value of %s is %s' % (key, value)
read_dict(the_dict_object)