面试题:未知嵌套层数的字典获取值为特定值的所有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的路径,把上面代码稍微改改就好了。

posted @ 2022-05-22 20:13  水天需  阅读(48)  评论(0编辑  收藏  举报