使用变量作为字典键集 [英] Use Variable As Dictionary Key Set
问题描述
我将JSON文件解析为字典,例如下面的JSON数据
I parse a JSON file to a dictionary, example JSON data below
{
"environmental": {
"temprature": {
"test" : "temprature",
"unit": "c",
"now": 12.65,
"now_timestamp": "10-06-2019 08:02:18",
"min": "12.5",
"min_timestamp": "03-06-2019 07:40:02",
"max": "32.84",
"max_timestamp": "03-06-2019 04:30:03"
}
}
}
我想使用列表元组或字符串作为字典键来检索值或设置值.
I would like to either retrieve a value or set a value using a list tuple or string as the dictionary key.
var_lst_key = ["environmental", "temprature", "now"]
var_dict_x[var_lst_key] = "x"
或
print(var_dict_x[var_lst_key])
推荐答案
第1部分:做到简单:使用函数
嵌套查找非常容易.您遍历键,然后继续用您当前正在查看的键上的值替换您要寻找的对象:
Part 1: Doing it the easy way: using functions
A nested lookup is pretty easy to do. You iterate over the keys, and keep replacing the object you're looking into with the value at the key you're currently looking at:
def nested_get(obj, keys):
for key in keys:
obj = obj[key]
return obj
def nested_set(obj, keys, value):
for key in keys[:-1]:
# Drill down until the penultimate key
obj = obj[key]
# Set value of last key
obj[keys[-1]] = value
要运行此命令:
jstr = """{ "environmental": {
"temprature": {
"test" : "temprature",
"unit": "c",
"now": 12.65,
"now_timestamp": "10-06-2019 08:02:18",
"min": "12.5",
"min_timestamp": "03-06-2019 07:40:02",
"max": "32.84",
"max_timestamp": "03-06-2019 04:30:03"
}
}}"""
jobj = json.loads(jstr)
var_lst_key = ["environmental", "temprature", "now"]
nested_lookup(jobj, var_lst_key) # Returns 12.65
invalid_keys = ["environmental", "temprature", "hello"]
nested_lookup(jobj, invalid_keys) # throws KeyError 'hello'
nested_set(jobj, var_lst_key, "HELLO!")
nested_lookup(jobj, var_lst_key) # Returns HELLO!
第2部分:花哨的方法:使用派生类
现在,如果您真的要使用 dict [key] = value
语法,则必须扩展 dict
类重写其 __ getitem __()
和 __ setitem __()
方法.
Part 2: Doing it the fancy way: using a derived class
Now if you really want to use the dict[key] = value
syntax, you're going to have to extend the dict
class to override its __getitem__()
and __setitem__()
methods.
class NestedLookupDict(dict):
def __init__(self, *args, **kwargs):
super(type(self), self).__init__(*args, **kwargs)
self.insert_missing_keys = True
def __getitem__(self, indices):
# Get the super dictionary for easy lookup
obj = self
for i in indices:
obj = dict.__getitem__(obj, i)
return obj
def __setitem__(self, indices, value):
# Get the base dictionary
obj = self
# Drill down until the penultimate key
for i in indices[:-1]:
# Insert a new dict if a key is missing
if self.insert_missing_keys and not dict.__contains__(obj, i):
dict.__setitem__(obj, i, dict())
obj = dict.__getitem__(obj, i)
# Set the value at the final key
dict.__setitem__(obj, indices[-1], value)
要使用此功能,让我们像以前一样使用从字符串中解析出的json对象:
To use this, let's use the json object parsed from the string like before:
# jobj = {... something ...}
nested_dict = NestedLookupDict(jobj)
print(nested_dict[var_lst_key]) # Prints 12.65
nested_dict[var_lst_key] = "HELLO!"
print(nested_dict[var_lst_key]) # Prints HELLO!
当 nested_dict.insert_missing_keys
设置为 True
(默认情况下)时, __ setitem __()
方法会在需要时添加缺少的字典.
When nested_dict.insert_missing_keys
is set to True
(by default), the __setitem__()
method adds missing dictionaries if required.
newkey = ["environmental", "temprature", "newkey"]
nested_dict[newkey] = "NEWKEY!!!"
print(nested_dict[newkey]) # Prints NEWKEY!!!
newkey2 = ["environmental", "temprature", "nested", "newkey"]
nested_dict[newkey2] = "NESTEDNEWKEY!!!"
print(nested_dict[newkey2]) # Prints NESTEDNEWKEY!!!
在所有这些操作的最后,您可以将对象转储到json来查看其外观:
At the end of all this, you can dump the object to json to see what it looks like:
print(json.dumps(nested_dict))
# Output:
{
"environmental": {
"temprature": {
"test": "temprature",
"unit": "c",
"now": "HELLO!",
"now_timestamp": "10-06-2019 08:02:18",
"min": "12.5",
"min_timestamp": "03-06-2019 07:40:02",
"max": "32.84",
"max_timestamp": "03-06-2019 04:30:03",
"newkey": "NEWKEY!!!",
"nested": {
"newkey": "NESTEDNEWKEY!!!"
}
}
}
}
第3部分:过度杀戮,但是哦!如此有趣的代码:丰富了NestedLookupDict
其他功能,因此您几乎可以像 dict
一样使用它:
- 使用
del nested_dict [key]
删除键 - 检查键是否与nested_dict 中的
-
nested_dict.get(键,默认值)
在key
不存在的情况下吸收KeyError
,并返回default 代码>
- 对
键
进行类型检查:它们现在必须是list
或tuple
key存在
- Delete keys using
del nested_dict[key]
- Check if keys exist with
key in nested_dict
nested_dict.get(key, default)
absorbs theKeyError
ifkey
doesn't exist, and returnsdefault
- Implemented a type check on
keys
: they must belist
ortuple
now
怪癖:
- 由于实现
__ getitem __()
的方式,nested_dict [empty_list]
返回对nested_dict
的引用(本身).如果这是一件坏事,可以添加对空键的检查.但是,我认为以这种方式保留它不会带来任何问题.此怪癖的一些后果:- 要使此行为与
__ contains __()
的工作方式保持一致,__ contains __()
函数将为空的key
返回 True
./code>.nested_list中的[]:= True
- 根据定义,您不能设置
nested_list [[]]
.这会引发ValueError
- Because of the way
__getitem__()
is implemented,nested_dict[empty_list]
returns a reference tonested_dict
(itself). If this is a bad thing, a check for empty keys could be added. However, I don't see any problems coming from leaving it this way. Some consequences of this quirk:- To keep this behavior consistent with how
__contains__()
works, the__contains__()
function returnsTrue
for emptykey
.[] in nested_list := True
- You cannot, by definition, set
nested_list[[]]
. That throws a ValueError
class NestedLookupDict(dict): def __init__(self, *args, **kwargs): super(type(self), self).__init__(*args, **kwargs) self.insert_missing_keys = True def check_keys(self, keys): if not isinstance(keys, (list, tuple)): raise TypeError("keys must be of type list or tuple") def get(self, keys, default=None): self.check_keys(keys) try: return self.__getitem__(keys) except KeyError: return default def __contains__(self, keys): self.check_keys(keys) if not keys: return True # nested_dict contains the key [] = itself if len(keys) > 1: return self.__getitem__(keys[:-1]).__contains__(keys[-1]) else: return dict.__contains__(self, keys[0]) def __delitem__(self, keys): self.check_keys(keys) obj = self for i in keys[:-1]: obj = dict.__getitem__(obj, i) dict.__delitem__(obj, keys[-1]) def __getitem__(self, keys): self.check_keys(keys) # Get the super dictionary for easy lookup obj = self for i in keys: obj = dict.__getitem__(obj, i) return obj def __setitem__(self, keys, value): self.check_keys(keys) if not keys: raise ValueError("keys cannot be empty") # Get the base dictionary obj = self # Drill down until the penultimate key for i in keys[:-1]: # Insert a new dict if a key is missing if self.insert_missing_keys and not dict.__contains__(obj, i): dict.__setitem__(obj, i, dict()) obj = dict.__getitem__(obj, i) # Set the value at the final key dict.__setitem__(obj, keys[-1], value)
这篇关于使用变量作为字典键集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- To keep this behavior consistent with how
- 要使此行为与