搜索值并获取父词典名称(键):
Dictionary = {dict1:{
'part1': {
'.wbxml': 'application/vnd.wap.wbxml',
'.rl': 'application/resource-lists+xml',
},
'part2':
{'.wsdl': 'application/wsdl+xml',
'.rs': 'application/rls-services+xml',
'.xop': 'application/xop+xml',
'.svg': 'image/svg+xml',
},
'part3':{...}, ...
dict2:{
'part1': { '.dotx': 'application/vnd.openxmlformats-..'
'.zaz': 'application/vnd.zzazz.deck+xml',
'.xer': 'application/patch-ops-error+xml',}
},
'part2':{...},
'part3':{...},...
},...
在上面的字典中,我需要搜索像"image/svg+xml"
这样的值。其中,没有值在字典中重复。如何搜索"image/svg+xml"
?所以它应该返回字典{ dict1:"part2" }
中的父键。
请注意:解决方案应该未经修改 Python 2.7和Python 3.3。
答案 0 :(得分:14)
这是一个简单的递归版本:
def getpath(nested_dict, value, prepath=()):
for k, v in nested_dict.items():
path = prepath + (k,)
if v == value: # found value
return path
elif hasattr(v, 'items'): # v is a dict
p = getpath(v, value, path) # recursive call
if p is not None:
return p
示例:
print(getpath(dictionary, 'image/svg+xml'))
# -> ('dict1', 'part2', '.svg')
答案 1 :(得分:5)
这是对嵌套dicts的迭代遍历,它还会跟踪导致特定点的所有键。因此,只要在dicts中找到正确的值,您就已经拥有了达到该值所需的密钥。
如果您将代码放在.py文件中,则以下代码将按原样运行。 find_mime_type(...)
函数返回将从原始字典中获取所需值的键序列。 demo()
函数显示了如何使用它。
d = {'dict1':
{'part1':
{'.wbxml': 'application/vnd.wap.wbxml',
'.rl': 'application/resource-lists+xml'},
'part2':
{'.wsdl': 'application/wsdl+xml',
'.rs': 'application/rls-services+xml',
'.xop': 'application/xop+xml',
'.svg': 'image/svg+xml'}},
'dict2':
{'part1':
{'.dotx': 'application/vnd.openxmlformats-..',
'.zaz': 'application/vnd.zzazz.deck+xml',
'.xer': 'application/patch-ops-error+xml'}}}
def demo():
mime_type = 'image/svg+xml'
try:
key_chain = find_mime_type(d, mime_type)
except KeyError:
print ('Could not find this mime type: {0}'.format(mime_type))
exit()
print ('Found {0} mime type here: {1}'.format(mime_type, key_chain))
nested = d
for key in key_chain:
nested = nested[key]
print ('Confirmation lookup: {0}'.format(nested))
def find_mime_type(d, mime_type):
reverse_linked_q = list()
reverse_linked_q.append((list(), d))
while reverse_linked_q:
this_key_chain, this_v = reverse_linked_q.pop()
# finish search if found the mime type
if this_v == mime_type:
return this_key_chain
# not found. keep searching
# queue dicts for checking / ignore anything that's not a dict
try:
items = this_v.items()
except AttributeError:
continue # this was not a nested dict. ignore it
for k, v in items:
reverse_linked_q.append((this_key_chain + [k], v))
# if we haven't returned by this point, we've exhausted all the contents
raise KeyError
if __name__ == '__main__':
demo()
输出:
在这里找到image / svg + xml mime类型:['dict1','part2','。svg']
确认查询:image / svg + xml
答案 2 :(得分:1)
以下是两种类似的快速和脏的方法来执行此类操作。函数find_parent_dict1使用列表推导但如果你对此感到不舒服,那么find_parent_dict2使用臭名昭着的嵌套for循环。
Dictionary = {'dict1':{'part1':{'.wbxml':'1','.rl':'2'},'part2':{'.wbdl':'3','.rs':'4'}},'dict2':{'part3':{'.wbxml':'5','.rl':'6'},'part4':{'.wbdl':'1','.rs':'10'}}}
value = '3'
def find_parent_dict1(Dictionary):
for key1 in Dictionary.keys():
item = {key1:key2 for key2 in Dictionary[key1].keys() if value in Dictionary[key1][key2].values()}
if len(item)>0:
return item
find_parent_dict1(Dictionary)
def find_parent_dict2(Dictionary):
for key1 in Dictionary.keys():
for key2 in Dictionary[key1].keys():
if value in Dictionary[key1][key2].values():
print {key1:key2}
find_parent_dict2(Dictionary)
答案 3 :(得分:0)
这是一种适用于嵌套列表和字典的复杂数据结构的解决方案
composer require larabook/gateway
[[[[[['d','dict1','part2','.svg','image / svg + xml']]]]]
包含字典和列表的复杂示例:
def search(d,search_pattern,prev_datapoint_path=[]):
output = []
current_datapoint = d
current_datapoint_path = prev_datapoint_path.copy()
if type(current_datapoint) is dict:
for dkey in current_datapoint:
if search_pattern in str(dkey):
c = current_datapoint_path.copy()
c.append(dkey)
output.append(c)
c = current_datapoint_path.copy()
c.append(dkey)
output.append(search(current_datapoint[dkey],search_pattern,c))
elif type(current_datapoint) is list:
for i in range(0,len(current_datapoint)):
if search_pattern in str(i):
output.append(current_datapoint_path.append(i))
c= current_datapoint_path.copy()
c.append(i)
output.append(search(current_datapoint[i],search_pattern,c))
elif search_pattern in str(current_datapoint):
c = current_datapoint_path.copy()
c.append(current_datapoint)
output.append(c)
output = filter(None, output)
return list(output)enter code here
if __name__ == "__main__":
d = {'dict1':
{'part1':
{'.wbxml': 'application/vnd.wap.wbxml',
'.rl': 'application/resource-lists+xml'},
'part2':
{'.wsdl': 'application/wsdl+xml',
'.rs': 'application/rls-services+xml',
'.xop': 'application/xop+xml',
'.svg': 'image/svg+xml'}},
'dict2':
{'part1':
{'.dotx': 'application/vnd.openxmlformats-..',
'.zaz': 'application/vnd.zzazz.deck+xml',
'.xer': 'application/patch-ops-error+xml'}}}
print(search(d, 'image/svg+xml', ['d']))