【问题标题】:Pythonic way of accessing recursively nested dict [duplicate]访问递归嵌套字典的Pythonic方式[重复]
【发布时间】:2014-09-13 09:37:06
【问题描述】:

在一般情况下,我们如何对嵌套字典进行递归访问?

from collections import defaultdict

D = lambda: defaultdict(D)
d = D()

keys = ['k1', 'k2', 'k3']
value = 'v'

if len(keys) == 3:
    k1, k2, k3 = keys
    d[k1][k2][k3] = value
else:
    ???

我正走在reduced.__getitem__d.__setitem__ 这条可怕的道路上,但我觉得肯定有更优雅的方式......

【问题讨论】:

  • 很高兴找到@Dave。您的搜索算法比 SO 对相关问题的搜索要好。
  • 确实很好找。关闭我自己的问题作为重复... :)

标签: python recursion dictionary


【解决方案1】:

这很丑陋,但这有效:

def set_val(d, keys, val):
    reduce(lambda x,y: x[y], keys[:-1], d)[keys[-1]] = val

更易读的版本:

def set_val(d, keys, val):
    last = keys[-1]  # Key we want to set val on
    search_keys = keys[:-1]  # Keys we need to traverse
    reduce(lambda x,y: x[y], search_keys, d)[last] = val

用法:

>>> from collections import defaultdict
>>> D = lambda: defaultdict(D)
>>> d = D()
>>> set_val(d, ['k1', 'k2', 'k3'], "hi")
>>> d
defaultdict(<function <lambda> at 0x7fbd365ac7d0>, {'k1': defaultdict(<function <lambda> at 0x7fbd365ac7d0>, {'k2': defaultdict(<function <lambda> at 0x7fbd365ac7d0>, {'k3': 'hi'})})})
>>> d['k1']['k2']['k3']
'hi'

它使用reduce 到达请求的最内层字典 (keys[:-1]),然后将列表中的最后一个键设置为所需的值 (output_of_reduce[keys[-1]] = val)。

请注意,在 Python 3 中,您需要来自 functools import reduce 才能使用它。

为了清楚起见,这里是扩展的代码:

def set_val(d, keys, val):
    out = d
    for k in keys[:-1]:
        out = out[k]
    out[keys[-1]] = val

【讨论】:

  • 这确实有效,但我希望有一个更优雅的想法..
  • 我知道我迟到了,但感谢这段代码。从来没有想过reduce可以这样使用! 2021 年还有更好的方法吗?
【解决方案2】:

你可以只使用递归。不能说它比循环或使用 reduce 更优雅或更 Pythonic。

def assign(dct, keylist, value):
    if not keylist:
        dct = value
    else:
        dct[keylist[0]] = assign(dct[keylist[0]], keylist[1:], value)
    return dct


if __name__ == '__main__':
    from collections import defaultdict
    D = lambda: defaultdict(D)
    d = D()
    keys = ['k1', 'k2', 'k3']
    value = 'v'
    assign(d, keys, value)
    print d['k1']['k2']['k3']

[prints] 'v'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-08
    • 2012-05-11
    • 1970-01-01
    • 2020-10-19
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多