提问人:boondockorphan 提问时间:10/7/2023 最后编辑:John Gordonboondockorphan 更新时间:10/7/2023 访问量:104
如何创建项目并将其添加到嵌套词典中?
How do you create and add items to a nested dictionary?
问:
我想遍历一个列表,首先检查字典中是否存在一个项目,如果存在,我想跳过它并继续前进,如果没有,我想将其添加到字典中的相应级别。
我从空字典和这个列表列表开始
my_dictionary = {}
file1 = ['model_a', 'part_a', 'category_a', 'format_a', 'version_a', 'filename_a']
file2 = ['model_b', 'part_a', 'category_a', 'format_a', 'version_a', 'filename_a']
file3 = ['model_a', 'part_b', 'category_a', 'format_a', 'version_a', 'filename_b']
file4 = ['model_c', 'part_a', 'category_a', 'format_a', 'version_a', 'filename_a']
file5 = ['model_b', 'part_a', 'category_a', 'format_b', 'version_a', 'filename_a']
file6 = ['model_a', 'part_a', 'category_a', 'format_a', 'version_b', 'filename_a']
file_list = [file1, file2, file3, file4, file5, file6]
我创建了一个循环并创建变量来检查并写入字典:
for item in file_list:
model, pn, category, file_format, version, filename = item
我的目标是:
{
"model_a": {
"part_a": {
"category_a": {
"format_a": {
"version_a": "filename_a",
"version_b": "filename_a"
}
}
},
"part_b": {
"category_a": {
"format_a": {
"version_a": "filename_b"
}
}
}
},
"model_b": {
"part_a": {
"category_a": {
"format_a": {
"version_a": "filename_a"
},
"format_b": {
"version_a": "filename_a"
}
}
}
},
"model_c": {
"part_a": {
"category_a": {
"format_a": {
"version_a": "filename_a"
}
}
}
}
}
第一次尝试只是在每个循环中写入项目,而不先检查:
# first attempt
for item in file_list:
model, pn, category, file_format, version, filename = item
my_object = {pn: {category: {file_format: {version: filename}}}}
my_dictionary[model] = my_object
这使得它通过循环,但覆盖项目而不是添加缺失的部分。
接下来的尝试是使用 try/except 并逐步遍历字典的每个级别来检查键。它在第一级工作,并生成缺少的密钥,并跳过现有密钥。
try:
my_dictionary[model]
except (KeyError, IndexError):
model_exists = False
else:
model_exists = True
if not model_exists:
my_dictionary[model] = {pn}
在此步骤中,我成功创建了一个值为 key = pn 的 key = 模型,但是当我在下一个级别尝试相同的方法时:
try:
my_dictionary[model][pn]
我得到:“TypeError:'set'对象不可下标。我正在运行 3.10.1,我在那里订购了字典。
我觉得这可能是一个解决方案:从嵌套列表创建一个嵌套词典,因为发布的问题看起来像我想做的事情,但老实说,这对我来说毫无意义。
答:
1赞
JonSG
10/7/2023
#1
在这里,是你的朋友。dictionary 方法将帮助我们初始化给定键所需的子字典。如果你用过,那么你已经有了基本的了解。当然,这里也可以使用嵌套。我更喜欢它,因为它最终给你留下了一本普通的旧词典。setdefault()
setdefault()
collections.defaultdict()
defaultdict()
setdefault()
defaultdict()
请注意,我奇怪地格式化了这一行,以便更容易阅读。
import json
file1 = ['model_a', 'part_a', 'category_a', 'format_a', 'version_a', 'filename_a']
file2 = ['model_b', 'part_a', 'category_a', 'format_a', 'version_a', 'filename_a']
file3 = ['model_a', 'part_b', 'category_a', 'format_a', 'version_a', 'filename_b']
file4 = ['model_c', 'part_a', 'category_a', 'format_a', 'version_a', 'filename_a']
file5 = ['model_b', 'part_a', 'category_a', 'format_b', 'version_a', 'filename_a']
file6 = ['model_a', 'part_a', 'category_a', 'format_a', 'version_b', 'filename_a']
file_list = [file1, file2, file3, file4, file5, file6]
my_dictionary = {}
for model, pn, category, file_format, version, filename in file_list:
my_dictionary \
.setdefault(model, {}) \
.setdefault(pn, {}) \
.setdefault(category, {}) \
.setdefault(file_format, {})[version] = filename
print(json.dumps(my_dictionary, indent=4))
这也可能有助于说明正在发生的事情。
my_dictionary = {}
for model, pn, category, file_format, version, filename in file_list:
target = my_dictionary.setdefault(model, {})
target = target.setdefault(pn, {})
target = target.setdefault(category, {})
target = target.setdefault(file_format, {})
target[version] = filename
无论哪种格式,您都可以:
{
"model_a": {
"part_a": {
"category_a": {
"format_a": {
"version_a": "filename_a",
"version_b": "filename_a"
}
}
},
"part_b": {
"category_a": {
"format_a": {
"version_a": "filename_b"
}
}
}
},
"model_b": {
"part_a": {
"category_a": {
"format_a": {
"version_a": "filename_a"
},
"format_b": {
"version_a": "filename_a"
}
}
}
},
"model_c": {
"part_a": {
"category_a": {
"format_a": {
"version_a": "filename_a"
}
}
}
}
}
评论
1赞
boondockorphan
10/7/2023
谢谢!我尝试了您提供的东西,它奏效了,这非常好。我正在阅读有关setdefault的信息,以了解它为什么有效。我读了几篇文章,我需要练习使用它。对我最有帮助的是你对目标的说明=......目标 =。对我来说,这是一个完美的例证,说明在循环列表时如何使用 setdefault() 分配变量。再次感谢大家。
0赞
treuss
10/7/2023
#2
看起来像是递归的一个很好的用例:
def update_dict(dictionary, items):
if len(items) == 2:
dictionary[items[0]] = items[1]
else:
if items[0] not in dictionary:
dictionary[items[0]] = {}
update_dict(dictionary[items[0]], items[1:])
my_dictionary = {}
file1 = ['model_a', 'part_a', 'category_a', 'format_a', 'version_a', 'filename_a']
file2 = ['model_b', 'part_a', 'category_a', 'format_a', 'version_a', 'filename_a']
file3 = ['model_a', 'part_b', 'category_a', 'format_a', 'version_a', 'filename_b']
file4 = ['model_c', 'part_a', 'category_a', 'format_a', 'version_a', 'filename_a']
file5 = ['model_b', 'part_a', 'category_a', 'format_b', 'version_a', 'filename_a']
file6 = ['model_a', 'part_a', 'category_a', 'format_a', 'version_b', 'filename_a']
file_list = [file1, file2, file3, file4, file5, file6]
for file in file_list:
update_dict(my_dictionary, file)
递归函数也可以写得更短,使用:setdefault
def update_dict(dictionary, items):
if len(items) == 2:
dictionary[items[0]] = items[1]
else:
update_dict(dictionary.setdefault(items[0], {}), items[1:])
评论
{pn}
创建一个集合,而不是一个字典。