我想创建一个函数来递归遍历多维字典,其中维度是未知的。
这是我到目前为止所提出的,但它似乎没有正常工作。这将打印出一些键/值两次,它们不是有序的。
def walk_dict(d):
for k,v in d.items():
if isinstance(v, dict):
walk_dict(v)
else:
print "%s %s" % (k, v)
这是一个示例数组:
d = {
'plan_code': 'b',
'quantity': '1',
'account': {
'account_code': 'b',
'username': 'jdoe',
'email': 'jdoe@domain.com',
'first_name': 'b',
'last_name': 'b',
'company_name': 'Company, LLC.',
'billing_info': {
'first_name': 'b',
'last_name': 'b',
'address1': '123 Test St',
'city': 'San Francisco',
'state': 'CA',
'country': 'US',
'zip': '94105',
'credit_card': {
'number': '1',
'year': '2018',
'month': '12',
'verification_value': '123',
},
},
},
}
答案 0 :(得分:13)
我不确定你的最终目标是什么,但代码正在做它应该做的事情。您正在看到您认为重复项目的内容,因为有'first_name'这样的键/值组合:'b'都在'account'内,'billing_info'在'account'中。我不确定你要找的是什么订单,但字典是无序的,所以你打印它们的功能必须给它们一些订单,例如更换以下内容:
for k,v in d.items():
与
for k,v in sorted(d.items(),key=lambda x: x[0]):
或者你需要一本有序的字典。您也可以像这样使用pprint模块从dict中打印出一个漂亮的打印:
>>> import pprint
>>> pprint.pprint(d)
{'account': {'account_code': 'b',
'billing_info': {'address1': '123 Test St',
'city': 'San Francisco',
'country': 'US',
'credit_card': {'month': '12',
'number': '1',
'verification_value': '123',
'year': '2018'},
'first_name': 'b',
'last_name': 'b',
'state': 'CA',
'zip': '94105'},
'company_name': 'Company, LLC.',
'email': 'jdoe@domain.com',
'first_name': 'b',
'last_name': 'b',
'username': 'jdoe'},
'plan_code': 'b',
'quantity': '1'}
但是,我不完全确定你的最终目标是什么。此外,当值为词典时,您缺少键。我修改了你的代码以执行与pprint在下面的操作类似的事情:
def walk_dict(d,depth=0):
for k,v in sorted(d.items(),key=lambda x: x[0]):
if isinstance(v, dict):
print (" ")*depth + ("%s" % k)
walk_dict(v,depth+1)
else:
print (" ")*depth + "%s %s" % (k, v)
为你的例子dict产生:
>>> walk_dict(d)
account
account_code b
billing_info
address1 123 Test St
city San Francisco
country US
credit_card
month 12
number 1
verification_value 123
year 2018
first_name b
last_name b
state CA
zip 94105
company_name Company, LLC.
email jdoe@domain.com
first_name b
last_name b
username jdoe
plan_code b
quantity 1
答案 1 :(得分:3)
>>> import json
>>> print json.dumps(d, indent=4)
答案 2 :(得分:2)
这会正确打印键值对。你能指出哪些数据会被重复。基于以上数据可能会混淆这些键:
'first_name': 'b',
'last_name': 'b',
是两个词典的一部分 - “帐户”和“billing_info”。所以他们会在输出中出现两次。
此外,如果您想要某种顺序,您的词典K,V应该打印使用有序词典
答案 3 :(得分:1)
作为Justin Peel mentions,pprint.pprint
可能会做你想要的。
我认为您的代码存在的问题是您应该在递归之前先打印密钥,即更改
if isinstance(v, dict):
walk_dict(v)
到
if isinstance(v, dict):
print k
walk_dict(v)
虽然在任何情况下,除非你添加缩进等,否则它看起来会很混乱。
这种事实际上非常复杂;如果您想获得一些想法,请查看pprint
的代码。
答案 4 :(得分:1)
以下是Justin Peel接受的答案的变体,它将结果作为OrderedDict
返回,而不是打印结果。
from collections import OrderedDict
def sort_by_keys(dct,):
new_dct = OrderedDict({})
for item in sorted(dct.items(), key=lambda (key, val): key):
key = item[0]
val = item[1]
if isinstance(val, dict):
new_dct[key] = sort_by_keys(val)
else:
new_dct[key] = val
return new_dct
答案 5 :(得分:0)
你的代码完美无缺,它完全按照你所说的去做。
我在输出中看到的唯一重复是first_name和last_name,它们实际上定义了两次(在不同的字典中)。
关于'乱序'它是一本字典,它没有保证的顺序。也许它确实如此,但它将基于内部表示,你不应该依赖它。
您需要做的是按照您希望的方式对数据进行排序。您还可能希望打印出子字典的键值,以使输出更容易理解。
答案 6 :(得分:0)
在Python中,字典由键索引。键可以是任何不可变类型,如字符串或数字。除非键已排序,否则它们将始终以任意顺序返回。由于这个事实,您的walk_dict
正在打印看似随机的结果。
以下是walk_dict
打印所有键和值的示例。我已经在字典的每个级别对它们进行了排序。另外,我打印了每把钥匙。您的代码在递归之前没有打印密钥。最后,我添加了字符串填充以强调字典的每个级别。医生们都在路过。我希望这可以帮助你建立你的最终功能。
import doctest
def walk_dict(seq, level=0):
"""Recursively traverse a multidimensional dictionary and print all
keys and values.
>>> d = {'dog': 'dusty', 'cat': 'fluffy', 'bird': 'chirpy'}
>>> walk_dict(d)
bird chirpy
cat fluffy
dog dusty
>>> d = {'location': 'home', 'animals':{'dog': 'dusty', 'cat': 'fluffy', 'bird': 'chirpy'}}
>>> walk_dict(d)
animals
bird chirpy
cat fluffy
dog dusty
location home
>>> d = {'location': 'home', 'animals':{'dog': 'dusty', 'cat': 'fluffy', 'bird': {'name':'chirpy', 'color':'blue'}}}
>>> walk_dict(d)
animals
bird
color blue
name chirpy
cat fluffy
dog dusty
location home
>>> d = { \
'plan_code': 'b', \
'quantity': '1', \
'account': { \
'account_code': 'b', \
'username': 'jdoe', \
'email': 'jdoe@domain.com', \
'first_name': 'b', \
'last_name': 'b', \
'company_name': 'Company, LLC.', \
'billing_info': { \
'first_name': 'b', \
'last_name': 'b', \
'address1': '123 Test St', \
'city': 'San Francisco', \
'state': 'CA', \
'country': 'US', \
'zip': '94105', \
'credit_card': { \
'number': '1', \
'year': '2018', \
'month': '12', \
'verification_value': '123', \
}, \
}, \
}, \
}
>>> walk_dict(d)
account
account_code b
billing_info
address1 123 Test St
city San Francisco
country US
credit_card
month 12
number 1
verification_value 123
year 2018
first_name b
last_name b
state CA
zip 94105
company_name Company, LLC.
email jdoe@domain.com
first_name b
last_name b
username jdoe
plan_code b
quantity 1
"""
items = seq.items()
items.sort()
for v in items:
if isinstance(v[1], dict):
# Print the key before make a recursive call
print "%s%s" % (" " * level, v[0])
nextlevel = level + 1
walk_dict(v[1], nextlevel)
else:
print "%s%s %s" % (" " * level, v[0], v[1])
if __name__ == '__main__':
doctest.testmod()
答案 7 :(得分:0)
到目前为止,提到的解决方案并不能满足我的要求,但是使用贾斯汀·皮尔(Justin Peel)的拼写版本工作时,我能够以自己想要的方式打印出一些东西:
def dict_parser(data, depth=0):
if isinstance(data, dict):
for key in data:
value = data[key]
print(' ') * depth + '"' + key + '":'
dict_parser(value, depth + 1)
elif isinstance(data, list):
for item in data:
if isinstance(item, list):
dict_parser(item, depth + 1)
else:
print(' ') * depth + '"' + item + '"'
elif isinstance(data, bool):
print(' ') * depth + str(data)
else:
print(' ') * depth + '"' + data + '"'
其中印有以下内容:
"saved_skels":
"E:\Child_Skeleton_6ft.fbx"
"E:\Female_Skeleton_6ft.fbx"
"E:\HeroFemale_Skeleton.fbx"
"E:\HeroMale_Skeleton.fbx"
"saved_roots":
"E:\users\Characters"
"E:\content\characters"
"saved_tabs":
"Characters":
"ProxyFemale":
"HeroFemale_Skeleton.fbx"
"animation":
"HeroFemale_Skeleton.fbx"
"ProxyMale":
"HeroMale_Skeleton.fbx"
"Game":
""
"Proto":
"Female":
"Female_Skeleton_NewBP.fbx"
"Assets":
""
"characters":
"player":
"player_Skeleton.fbx"
"actor":
"Hero_Skeleton.fbx"
"edit_common_checkbox_state":
False
"get_latest_checkbox_state":
True