我有一个复杂的字典结构,我想通过一个关键字列表来访问它,以找到正确的条目。
dataDict = {
"a":{
"r": 1,
"s": 2,
"t": 3
},
"b":{
"u": 1,
"v": {
"x": 1,
"y": 2,
"z": 3
},
"w": 3
}
}
maplist = ["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
发布于 2013-02-05 02:07:38
使用reduce()
遍历字典:
from functools import reduce # forward compatibility for Python 3
import operator
def getFromDict(dataDict, mapList):
return reduce(operator.getitem, mapList, dataDict)
并重用getFromDict
来查找存储setInDict()
的值的位置
def setInDict(dataDict, mapList, value):
getFromDict(dataDict, mapList[:-1])[mapList[-1]] = value
mapList
中除了最后一个元素之外的所有元素都需要找到要向其添加值的“父”字典,然后使用最后一个元素将值设置为正确的键。
演示:
>>> getFromDict(dataDict, ["a", "r"])
1
>>> getFromDict(dataDict, ["b", "v", "y"])
2
>>> setInDict(dataDict, ["b", "v", "w"], 4)
>>> import pprint
>>> pprint.pprint(dataDict)
{'a': {'r': 1, 's': 2, 't': 3},
'b': {'u': 1, 'v': {'w': 4, 'x': 1, 'y': 2, 'z': 3}, 'w': 3}}
请注意,Python PEP8样式指南prescribes snake_case names for functions。上面的方法同样适用于列表或字典和列表的混合,因此名称实际上应该是get_by_path()
和set_by_path()
from functools import reduce # forward compatibility for Python 3
import operator
def get_by_path(root, items):
"""Access a nested object in root by item sequence."""
return reduce(operator.getitem, items, root)
def set_by_path(root, items, value):
"""Set a value in a nested object in root by item sequence."""
get_by_path(root, items[:-1])[items[-1]] = value
为了完整起见,我们使用一个删除键的函数:
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]]
发布于 2016-04-29 12:38:54
使用reduce很聪明,但是如果父键没有预先存在于嵌套字典中,那么OP的set方法可能会出现问题。由于这是我在谷歌搜索中看到的第一篇关于这个主题的帖子,我想把它做得稍微好一点。
( Setting a value in a nested python dictionary given a list of indices and value )中的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()], [])
它的一个用途是使用以下代码将嵌套树转换为pandas DataFrame (假设嵌套字典中的所有leafs都具有相同的深度)。
def dict_to_df(dataDict):
ret = []
for k in keysInDict(dataDict):
v = np.array( getFromDict(dataDict, k), )
v = pd.DataFrame(v)
v.columns = pd.MultiIndex.from_product(list(k) + [v.columns])
ret.append(v)
return reduce(pd.DataFrame.join, ret)
发布于 2017-03-01 10:07:58
与其每次查找一个值都会影响性能,不如将字典展平一次,然后简单地查找关键字,如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
。
而不是在每次查找时遍历字典,您可以通过扁平化字典并保存输出来加速这一过程,以便从冷启动的查找将意味着加载扁平化的字典,并简单地执行键/值查找而不遍历。
https://stackoverflow.com/questions/14692690
复制相似问题