Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 是否通过键列表访问嵌套字典项?_Python_List_Dictionary - Fatal编程技术网

Python 是否通过键列表访问嵌套字典项?

Python 是否通过键列表访问嵌套字典项?,python,list,dictionary,Python,List,Dictionary,我有一个复杂的字典结构,我想通过一个键列表来访问它,以找到正确的项 dataDict={ “a”:{ “r”:1, “s”:2, “t”:3 }, “b”:{ “u”:1, “五”:{ “x”:1, “y”:2, “z”:3 }, “w”:3 } } 地图列表=[“a”,“r”] 或 maplist = ["b", "v", "y"] 我已经编写了以下代码,这些代码很有效,但我相信如果有人有想法,会有更好、更有效的方法来实现这一点 # Get a given data from a

我有一个复杂的字典结构,我想通过一个键列表来访问它,以找到正确的项

dataDict={
“a”:{
“r”:1,
“s”:2,
“t”:3
},
“b”:{
“u”:1,
“五”:{
“x”:1,
“y”:2,
“z”:3
},
“w”:3
}
}    
地图列表=[“a”,“r”]

maplist = ["b", "v", "y"]
我已经编写了以下代码,这些代码很有效,但我相信如果有人有想法,会有更好、更有效的方法来实现这一点

# Get a given data from a dictionary with position provided as a list
def getFromDict(dataDict, mapList):    
    for k in mapList: dataDict = dataDict[k]
    return dataDict

# Set a given data in a dictionary with position provided as a list
def setInDict(dataDict, mapList, value): 
    for k in mapList[:-1]: dataDict = dataDict[k]
    dataDict[mapList[-1]] = value
使用
reduce()
遍历字典:

from functools import reduce  # forward compatibility for Python 3
import operator

def getFromDict(dataDict, mapList):
    return reduce(operator.getitem, mapList, dataDict)
并重用
getFromDict
,找到存储
setindicat()值的位置。

除了
映射列表中的最后一个元素之外,所有元素都需要找到要向其中添加值的“父”字典,然后使用最后一个元素将值设置为右键

演示:

请注意,Python PEP8样式指南。上述方法同样适用于列表或字典与列表的混合,因此名称应该是
get\u by\u path()
set\u by\u path()

为了完整起见,删除密钥的函数:

def del_by_path(root, items):
    """Delete a key-value in a nested object in root by item sequence."""
    del get_by_path(root, items[:-1])[items[-1]]
使用
reduce()
遍历字典:

from functools import reduce  # forward compatibility for Python 3
import operator

def getFromDict(dataDict, mapList):
    return reduce(operator.getitem, mapList, dataDict)
并重用
getFromDict
,找到存储
setindicat()值的位置。

除了
映射列表中的最后一个元素之外,所有元素都需要找到要向其中添加值的“父”字典,然后使用最后一个元素将值设置为右键

演示:

请注意,Python PEP8样式指南。上述方法同样适用于列表或字典与列表的混合,因此名称应该是
get\u by\u path()
set\u by\u path()

为了完整起见,删除密钥的函数:

def del_by_path(root, items):
    """Delete a key-value in a nested object in root by item sequence."""
    del get_by_path(root, items[:-1])[items[-1]]

此库可能有帮助:

用于通过访问和搜索词典的python库 /使用xpath的斜杠/路径

基本上,它可以让你像浏览字典一样浏览字典 文件系统


此库可能有帮助:

用于通过访问和搜索词典的python库 /使用xpath的斜杠/路径

基本上,它可以让你像浏览字典一样浏览字典 文件系统


使用reduce很聪明,但是如果嵌套字典中没有父键,OP的set方法可能会有问题。由于这是我在谷歌搜索中看到的第一篇关于这个主题的SO帖子,我想让它稍微好一点

()中的set方法似乎对缺少父密钥更为健壮。要复制它,请执行以下操作:

def nested_set(dic, keys, value):
    for key in keys[:-1]:
        dic = dic.setdefault(key, {})
    dic[keys[-1]] = value
此外,还可以方便地使用一种方法遍历密钥树并获取我为其创建的所有绝对密钥路径:

def keysInDict(dataDict, parent=[]):
    if not isinstance(dataDict, dict):
        return [tuple(parent)]
    else:
        return reduce(list.__add__, 
            [keysInDict(v,parent+[k]) for k,v in dataDict.items()], [])
它的一个用途是使用以下代码将嵌套树转换为数据帧(假设嵌套字典中的所有叶具有相同的深度)


使用reduce很聪明,但是如果嵌套字典中没有父键,OP的set方法可能会有问题。由于这是我在谷歌搜索中看到的第一篇关于这个主题的SO帖子,我想让它稍微好一点

()中的set方法似乎对缺少父密钥更为健壮。要复制它,请执行以下操作:

def nested_set(dic, keys, value):
    for key in keys[:-1]:
        dic = dic.setdefault(key, {})
    dic[keys[-1]] = value
此外,还可以方便地使用一种方法遍历密钥树并获取我为其创建的所有绝对密钥路径:

def keysInDict(dataDict, parent=[]):
    if not isinstance(dataDict, dict):
        return [tuple(parent)]
    else:
        return reduce(list.__add__, 
            [keysInDict(v,parent+[k]) for k,v in dataDict.items()], [])
它的一个用途是使用以下代码将嵌套树转换为数据帧(假设嵌套字典中的所有叶具有相同的深度)


循环使用
似乎更像是一个python。
请参阅引用自

已删除
reduce()
。如果您确实需要,请使用
functools.reduce()
;但是,99%的时候,显式
for
循环更具可读性

请注意,接受的解决方案不会设置不存在的嵌套键(它会引发
KeyError
)。使用以下方法将创建不存在的节点:

def nested_set(dic, keys, value):
    for key in keys[:-1]:
        dic = dic.setdefault(key, {})
    dic[keys[-1]] = value

代码在Python2和Python3中都能工作。

使用
for
循环似乎更像Python。 请参阅引用自

已删除
reduce()
。如果您确实需要,请使用
functools.reduce()
;但是,99%的时候,显式
for
循环更具可读性

请注意,接受的解决方案不会设置不存在的嵌套键(它会引发
KeyError
)。使用以下方法将创建不存在的节点:

def nested_set(dic, keys, value):
    for key in keys[:-1]:
        dic = dic.setdefault(key, {})
    dic[keys[-1]] = value

代码在Python2和Python3中都可以使用。

与其每次都要查找一个值,不如将字典展平一次,然后像
b:v:y

def flatten(mydict):
  new_dict = {}
  for key,value in mydict.items():
    if type(value) == dict:
      _dict = {':'.join([key, _key]):_value for _key, _value in flatten(value).items()}
      new_dict.update(_dict)
    else:
      new_dict[key]=value
  return new_dict

dataDict = {
"a":{
    "r": 1,
    "s": 2,
    "t": 3
    },
"b":{
    "u": 1,
    "v": {
        "x": 1,
        "y": 2,
        "z": 3
    },
    "w": 3
    }
}    

flat_dict = flatten(dataDict)
print flat_dict
{'b:w': 3, 'b:u': 1, 'b:v:y': 2, 'b:v:x': 1, 'b:v:z': 3, 'a:r': 1, 'a:s': 2, 'a:t': 3}
这样,您只需使用
flat_dict['b:v:y']
查找项目,它将为您提供
1


而不是在每次查找时遍历字典,您可以通过展平字典并保存输出来加快查找速度,这样冷启动时的查找就意味着加载展平字典,只需执行键/值查找而无需遍历。

而不是每次要查找值时都进行性能测试,你把字典展平一次,然后像
b:v:y

def flatten(mydict):
  new_dict = {}
  for key,value in mydict.items():
    if type(value) == dict:
      _dict = {':'.join([key, _key]):_value for _key, _value in flatten(value).items()}
      new_dict.update(_dict)
    else:
      new_dict[key]=value
  return new_dict

dataDict = {
"a":{
    "r": 1,
    "s": 2,
    "t": 3
    },
"b":{
    "u": 1,
    "v": {
        "x": 1,
        "y": 2,
        "z": 3
    },
    "w": 3
    }
}    

flat_dict = flatten(dataDict)
print flat_dict
{'b:w': 3, 'b:u': 1, 'b:v:y': 2, 'b:v:x': 1, 'b:v:z': 3, 'a:r': 1, 'a:s': 2, 'a:t': 3}
这样,您只需使用
flat_dict['b:v:y']
查找项目,它将为您提供
1


不必在每次查找时遍历字典,您可以通过展平字典并保存输出来加快查找速度,这样从冷启动开始的查找就意味着加载展平字典,只需执行键/值查找而不进行遍历。

使用递归函数如何

要获取值,请执行以下操作:

def getFromDict(dataDict, maplist):
    first, rest = maplist[0], maplist[1:]

    if rest: 
        # if `rest` is not empty, run the function recursively
        return getFromDict(dataDict[first], rest)
    else:
        return dataDict[first]
def setInDict(dataDict, maplist, value):
    first, rest = maplist[0], maplist[1:]

    if rest:
        try:
            if not isinstance(dataDict[first], dict):
                # if the key is not a dict, then make it a dict
                dataDict[first] = {}
        except KeyError:
            # if key doesn't exist, create one
            dataDict[first] = {}

        setInDict(dataDict[first], rest, value)
    else:
        dataDict[first] = value
并设置一个值:

def getFromDict(dataDict, maplist):
    first, rest = maplist[0], maplist[1:]

    if rest: 
        # if `rest` is not empty, run the function recursively
        return getFromDict(dataDict[first], rest)
    else:
        return dataDict[first]
def setInDict(dataDict, maplist, value):
    first, rest = maplist[0], maplist[1:]

    if rest:
        try:
            if not isinstance(dataDict[first], dict):
                # if the key is not a dict, then make it a dict
                dataDict[first] = {}
        except KeyError:
            # if key doesn't exist, create one
            dataDict[first] = {}

        setInDict(dataDict[first], rest, value)
    else:
        dataDict[first] = value

使用递归函数怎么样

要获取值,请执行以下操作:

def getFromDict(dataDict, maplist):
    first, rest = maplist[0], maplist[1:]

    if rest: 
        # if `rest` is not empty, run the function recursively
        return getFromDict(dataDict[first], rest)
    else:
        return dataDict[first]
def setInDict(dataDict, maplist, value):
    first, rest = maplist[0], maplist[1:]

    if rest:
        try:
            if not isinstance(dataDict[first], dict):
                # if the key is not a dict, then make it a dict
                dataDict[first] = {}
        except KeyError:
            # if key doesn't exist, create one
            dataDict[first] = {}

        setInDict(dataDict[first], rest, value)
    else:
        dataDict[first] = value
并设置一个值:

def getFromDict(dataDict, maplist):
    first, rest = maplist[0], maplist[1:]

    if rest: 
        # if `rest` is not empty, run the function recursively
        return getFromDict(dataDict[first], rest)
    else:
        return dataDict[first]
def setInDict(dataDict, maplist, value):
    first, rest = maplist[0], maplist[1:]

    if rest:
        try:
            if not isinstance(dataDict[first], dict):
                # if the key is not a dict, then make it a dict
                dataDict[first] = {}
        except KeyError:
            # if key doesn't exist, create one
            dataDict[first] = {}

        setInDict(dataDict[first], rest, value)
    else:
        dataDict[first] = value

纯Python风格,无任何导入:

def nested_set(element, value, *keys):
    if type(element) is not dict:
        raise AttributeError('nested_set() expects dict as first argument.')
    if len(keys) < 2:
        raise AttributeError('nested_set() expects at least three arguments, not enough given.')

    _keys = keys[:-1]
    _element = element
    for key in _keys:
        _element = _element[key]
    _element[keys[-1]] = value

example = {"foo": { "bar": { "baz": "ok" } } }
keys = ['foo', 'bar']
nested_set(example, "yay", *keys)
print(example)
纯Python风格,
>>> cfg= {'Options': [[1,[0]],[2,[4,[8,16]]],[3,[9]]]}
    ny = nested_yield(cfg, ['Options',1,1,1])
    ny.send(None)
[8, 16]
>>> ny.send('Hello!')
'Hello!'
>>> cfg
{'Options': [[1, [0]], [2, [4, 'Hello!']], [3, [9]]]}
>>> ny.close()
def gattr(d, *attrs):
    """
    This method receives a dict and list of attributes to return the innermost value of the give dict       
    """
    try:
        for at in attrs:
            d = d[at]
        return d
    except(KeyError, TypeError):
        return None


def sattr(d, *attrs):
    """
    Adds "val" to dict in the hierarchy mentioned via *attrs
    For ex:
    sattr(animals, "cat", "leg","fingers", 4) is equivalent to animals["cat"]["leg"]["fingers"]=4
    This method creates necessary objects until it reaches the final depth
    This behaviour is also known as autovivification and plenty of implementation are around
    This implementation addresses the corner case of replacing existing primitives
    https://gist.github.com/hrldcpr/2012250#gistcomment-1779319
    """
    for attr in attrs[:-2]:
        if type(d.get(attr)) is not dict:
            d[attr] = {}
        d = d[attr]
    d[attrs[-2]] = attrs[-1]
def getnestedvalue(dict, list):

    length = len(list)
    try:
        for depth, key in enumerate(list):
            if depth == length - 1:
                output = dict[key]
                return output
            dict = dict[key]
    except (KeyError, TypeError):
        return None

    return None
def get_sub_object_from_path(dict_name, map_list):
    for i in map_list:
        _string = "['%s']" % i
        dict_name += _string
    value = eval(dict_name)
    return value
#Sample:
_dict = {'new': 'person', 'time': {'for': 'one'}}
map_list = ['time', 'for']
print get_sub_object_from_path("_dict",map_list)
#Output:
#one
def set_at_path(data0, keys, value):
    data = deepcopy(data0)
    if len(keys)>1:
        if isinstance(data,dict):
            return {k:(set_by_path(v,keys[1:],value) if k==keys[0] else v) for k,v in data.items()}
        if isinstance(data,list):
            return [set_by_path(x[1],keys[1:],value) if x[0]==keys[0] else x[1] for x in enumerate(data)]
    else:
        data[keys[-1]]=value
        return data
def map_at_path(data0, keys, f):
    data = deepcopy(data0)
    if len(keys)>1:
        if isinstance(data,dict):
            return {k:(map_at_path(v,keys[1:],f) if k==keys[0] else v) for k,v in data.items()}
        if isinstance(data,list):
            return [map_at_path(x[1],keys[1:],f) if x[0]==keys[0] else x[1] for x in enumerate(data)]
    else:
        data[keys[-1]]=f(data[keys[-1]])
        return data
def nested_parse(nest, map_list):
    nestq = "nest['" + "']['".join(map_list) + "']"
    return eval(nestq, {'__builtins__':None}, {'nest':nest})
import pydash as _

_.get(dataDict, ["b", "v", "y"], default='Default')
def get_dictionary_value(dictionary_temp, variable_dictionary_keys):
     try:
          if(len(variable_dictionary_keys) == 0):
               return str(dictionary_temp)

          variable_dictionary_key = variable_dictionary_keys[0]
          variable_dictionary_keys.remove(variable_dictionary_key)

          return get_dictionary_value(dictionary_temp[variable_dictionary_key] , variable_dictionary_keys)

     except Exception as variable_exception:
          logging.error(variable_exception)
 
          return ''