英文:
Recursively modifying existing dictionary based on an array
问题
我有以下的输入变量:'PATH',它是一个包含要创建的键的数组,以及'output_content',它是一个字典,应该在其中创建这些键,'output content'已经包含键值对,它们不应该丢失。
例如,考虑PATH = ['patterns', 'pattern_1', 'children', 'pattern_1_1']
,结果的'output_content'字典应该如下所示:
{
'patterns': {
'pattern_1': {
'children': {
'pattern_1_1': {}
}
}
},
'already_existing_key': 'already_existing_value'
}
我尝试了以下方法:
current_dict = output_content
for key in PATH[1:]:
if key not in current_dict:
current_dict[key] = {}
current_dict = current_dict[key]
但很快我意识到这样做不会起作用,因为output_content根据current_dict在变化,所以最终的输出将只是{}
。
英文:
I have the the following input variables: 'PATH', which is an array containing keys to create to and 'output_content' which is a dictionary where the keys should be created in, 'output content' already contains key-value pairs, and they should not be lost.
For example: considering PATH = ['patterns', 'pattern_1', 'children', 'pattern_1_1']
, the resulting 'output_content' dictionary should look like this:
{
'patterns': {
'pattern_1': {
'children': {
'pattern_1_1': {}
}
}
},
'already_existing_key': 'already_existing_value'
}
I've tried the following:
current_dict = output_content
for key in PATH[1:]:
if key not in current_dict:
current_dict[key] = {}
current_dict = current_dict[key]
But soon i realized that the it just wouldn't work because output_content is changing according to current_dict, so the resulting output will be just {}
.
答案1
得分: 0
两个关于你的代码的注释:
* 你应该遍历整个列表 `PATH`,而不仅仅是 `PATH[1:]`。我看不到跳过第一个元素的理由。
* 如果条件 `key in current_dict` 被满足,那么你应该确保相关联的值是一个字典。
```python3
def add_path_to_dict(d, path):
for k in path:
if k not in d:
d[k] = {}
elif not isinstance(d[k], dict):
return
d = d[k]
d = {'z': 42}
add_path_to_dict(d, 'abcdefgh')
print(d)
# {'z': 42, 'a': {'b': {'c': {'d': {'e': {'f': {'g': {'h': {}}}}}}}}}
d = {'a': {'b': {'c':{'z': 42}}}}
add_path_to_dict(d, 'abcdefgh')
print(d)
# {'a': {'b': {'c': {'z': 42, 'd': {'e': {'f': {'g': {'h': {}}}}}}}}}
d = {'a': {'b': {'c':42}}}
add_path_to_dict(d, 'abcdefgh')
print(d)
# {'a': {'b': {'c': 42}}}
更进一步的建议:
- 与其使用空的
return
,你可以使用return 'Some error value'
,或者你可以raise ValueError(f'Key {k} already in dict and its value is not a dict.')
<details>
<summary>英文:</summary>
Two remarks with your code:
* You should iterate on the whole list `PATH`, not just `PATH[1:]`. I see no reason to skip the first element.
* If the condition `key in current_dict` is realised, then you should make sure that the associated value is a dict.
```python3
def add_path_to_dict(d, path):
for k in path:
if k not in d:
d[k] = {}
elif not isinstance(d[k], dict):
return
d = d[k]
d = {'z': 42}
add_path_to_dict(d, 'abcdefgh')
print(d)
# {'z': 42, 'a': {'b': {'c': {'d': {'e': {'f': {'g': {'h': {}}}}}}}}}
d = {'a': {'b': {'c':{'z': 42}}}}
add_path_to_dict(d, 'abcdefgh')
print(d)
# {'a': {'b': {'c': {'z': 42, 'd': {'e': {'f': {'g': {'h': {}}}}}}}}}
d = {'a': {'b': {'c':42}}}
add_path_to_dict(d, 'abcdefgh')
print(d)
# {'a': {'b': {'c': 42}}}
Further suggestions:
- Instead of the empty
return
, you couldreturn 'Some error value'
or you couldraise ValueError(f'Key {k} already in dict and its value is not a dict.')
答案2
得分: 0
如评论中所指出的,您的代码没有太多问题,只是路径中不必要的 [1:]
切片操作。
如果您想要更加简洁的写法,您可以使用 dict.setdefault
方法,避免需要测试键是否已经存在:
output_content = {'already_existing_key': 'already_existing_value'}
path = ['patterns', 'pattern_1', 'children', 'pattern_1_1']
current_dict = output_content
for key in path:
current_dict = current_dict.setdefault(key, {})
print(output_content)
演示:https://replit.com/@blhsing/UnusedDiscreteScriptinglanguages
英文:
As pointed out in the comments, there isn't much wrong with your code except the unnecessary [1:]
slice of the path.
If you're looking for a more concise way to write the code, you can use the dict.setdefault
method to avoid having to test if a key already exists:
output_content = {'already_existing_key': 'already_existing_value'}
path = ['patterns', 'pattern_1', 'children', 'pattern_1_1']
current_dict = output_content
for key in path:
current_dict = current_dict.setdefault(key, {})
print(output_content)
Demo: https://replit.com/@blhsing/UnusedDiscreteScriptinglanguages
答案3
得分: 0
答案中的代码如下:
@Stef 和 @blhsing 的两个答案都修改了原始的 `dict`,这可能不是你想要的行为。如果你需要一个副本,可以尝试以下解决方案:
```py
def add_path(path, dict_):
copied = dict_.copy()
dict_ = copied
for index, element in enumerate(path):
dict_ = dict_.setdefault(element, {})
if not isinstance(dict_, dict):
break
return copied
<details>
<summary>英文:</summary>
Both answers by @Stef and @blhsing modify the original `dict`, a behaviour which you may not want. Here's another solution if you need a copy:
```py
def add_path(path, dict_):
copied = dict_.copy()
dict_ = copied
for index, element in enumerate(path):
dict_ = dict_.setdefault(element, {})
if not isinstance(dict_, dict):
break
return copied
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论