面试题:未知嵌套层数的字典获取值为特定值的所有key
前两天面试,面试官先出了个这样的题:
如果有个JSON,是下面这样的结构,怎么求值为2的所有key?
{
"a":2,
"b":{"c":2,
"d":{"e":2},
"f":{"g":{"h":{"i":2}}}
.....
}
}
答曰:
好多层循环,暴力循环下完事
接着问:
你事先不知道它有些什么key, 也不知道嵌套多少层,怎么求呢?
答曰:
这个就不好办了,只能用递归了。
接着我就想着怎么写代码,面试官给打断了,说说出了递归思路就Ok了。(^-^)V
这不回来还是写一下,但是省去了序列化json的代码。
def getKeys(dic,target):
res = []
def backTrack(dic, target):
for item in dic.items():
if isinstance(item[1], dict):
backTrack(item[1],target)
else:
if item[1] == target:
res.append(item[0])
backTrack(dic, target)
return res
if __name__ == '__main__':
a = {'a':{'f':2, 'g':1}, 'b':{'c':2}, 'e':2, 'h':{'i':{'j':{'k':2,'m':1,'i':2}}}}
print(getKeys(a,2))
# 输出:['f', 'c', 'e', 'k', 'i']
如果要求包含某个字符的所有key(包括嵌套字典和数组里的嵌套字典),并输出key的路径,那么这样:
def getKeysIncludeList(dic: dict, pattern: str):
res = []
path = []
def backTrack(dic, pattern):
for item in dic.items():
if isinstance(item[1], dict):
path.append(item[0]) # 处理节点
backTrack(item[1], pattern)
path.pop() #回溯,撤销处理的节点
elif isinstance(item[1], list) :
if len(item[1]) > 0 and isinstance(item[1][0], dict): # 注意判断类型
path.append(item[0]) # 处理节点
#print('item[0]: {}, item[1][0]: {}'.format(item[0], item[1][0]))
backTrack(item[1][0], pattern)
path.pop() # 回溯,撤销处理的节点
else:
if len(re.findall(pattern, item[0], re.I)) > 0:
#print('item[0]: {}, pattern: {}, regResult: {}'.format(item[0], pattern,re.findall(pattern, item[0], re.I) ))
path.append(item[0])
res.append('->'.join(p for p in path[:]))
path.pop()
backTrack(dic, pattern)
return res
如果是要求值为value的所有key的路径,把上面代码稍微改改就好了。