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 ''