【问题标题】:Dynamically accessing nested dictionary keys?动态访问嵌套字典键?
【发布时间】:2016-10-02 15:41:09
【问题描述】:

当您一开始不知道要访问哪个键时,是否有一些简单的方法可以访问嵌套字典键?

例如:

dct = {'label': 'A', 'config': {'value': 'val1'}}

在这本字典中,我需要在另一个可以通过config 键访问的字典中访问label 键或value 键。

这取决于状态。

例如,如果我们有一个名为 label 的变量,那么如果:

label = True
if label:
   key = 'label'

在这种情况下它很简单:

dct[key]

现在如果标签为假并且我需要访问嵌套字典,我该如何动态指定它,这样我就不需要在每个迭代项目上使用 ifs(我的意思是每次检查是否使用 label 而不是 value ,因为我会在开始迭代充满dct 字典的字典之前知道这一点)?

喜欢:

label = False
if label:
   key = 'label'
else:
    key = 'config..?' # it should be something like ['config']['value']

【问题讨论】:

  • 您可以编写自己的字典类并覆盖__getitem__ 方法以使用dict['config.value'] - stackoverflow.com/questions/2390827/…
  • 或者只是将key 设为一个函数,例如key = lambda d: d['config']['value'].
  • @kennytm 实际上它并不那么容易工作,因为它使它成为一个函数,并希望我调用那个方法,比如dct[key(dct)],这并不能解决问题,因为那时我需要以不同的方式调用该键
  • @Andrius 如果将其设为函数,则在这两种情况下都将其称为result = key(dct),而不是result = dct[key(dct)]...

标签: python python-2.7 dictionary


【解决方案1】:

扩展@Barun 的工作,并可能帮助回答@Bhavani 关于嵌套字典中设置 值的问题,这里是动态访问或设置嵌套字典键的通用解决方案。 Python 3.7。

from typing import List

class DynamicAccessNestedDict:
    """Dynamically get/set nested dictionary keys of 'data' dict"""

    def __init__(self, data: dict):
        self.data = data

    def getval(self, keys: List):
        data = self.data
        for k in keys:
            data = data[k]
        return data

    def setval(self, keys: List, val) -> None:
        data = self.data
        lastkey = keys[-1]
        for k in keys[:-1]:  # when assigning drill down to *second* last key
            data = data[k]
        data[lastkey] = val

您只需将字典包装在此类的一个实例中,然后通过传递一个键列表来获取和设置。

dct = {'label': 'A', 'config': {'value': 'val1'}}

d = DynamicAccessNestedDict(dct)
assert d.getval(["label"]) == "A"
assert d.getval(["config", "value"]) == "val1"

# Set some new values
d.setval(["label"], "B")
d.setval(["config", "value"], "val2")

assert d.getval(["label"]) == "B"
assert d.getval(["config", "value"]) == "val2"

【讨论】:

    【解决方案2】:

    如果你知道要遍历的key,可以试试下面的方法。这适用于任何级别的嵌套字典。

    dct = {'label': 'A', 'config': {'value': 'val1'}}
    
    label = True
    key = ('label',)
    if not label:
        key = ('config', 'value')
    
    ret = dct
    for k in key:
      ret = ret[k]
    
    print ret
    

    【讨论】:

    • 在这种情况下如何更新“label”和“value”键的值。如果“label”作为参数传递,那么“label”的值应该被更新,如果“config”和“value”作为参数传递,那么相应的值应该被更新。
    【解决方案3】:
    from functools import reduce
    import operator
    #db is dictionary which need to update
    #keys is a list need to depth of keys in a order
    #value targeted value to update in dictionary 
    class Dict_update:
        def set_by_path(self, db, keys, value):
            """Set a value in a nested object in db by keys sequence."""
            for index in range(1,len(keys)):
                subitem = self.get_by_path(db, keys[:index])
                if not isinstance(subitem, dict):
                    self.get_by_path(db, keys[:index][:-1])[keys[:index][-1]] = {}
            self.get_by_path(db, keys[:-1])[keys[-1]] = value
            return db
    
        def get_by_path(self, db, keys):
    
            try: return reduce(operator.getitem, keys, db)
            except Exception as e:
                return None
    

    【讨论】:

    • 您能否添加一个示例,说明如何使用您的代码解决问题?
    猜你喜欢
    • 1970-01-01
    • 2011-07-23
    • 2018-02-09
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 2019-02-16
    相关资源
    最近更新 更多