python—高效地将扁平字符串解析为嵌套字典
我正在从一个专有数据库获取目录和项目的列表。列表也可以是巨大的,包含数千个视图和各种嵌套。列表示例:python—高效地将扁平字符串解析为嵌套字典,python,json,parsing,marshalling,Python,Json,Parsing,Marshalling,我正在从一个专有数据库获取目录和项目的列表。列表也可以是巨大的,包含数千个视图和各种嵌套。列表示例: "MIPK", "MIPK\/CM.toroidal", "MIPK\/CM.Supervoid", "MIPK\/DORAS", "MIPK\/DORAS\/CRUDE", "MIPK\/DORAS\/CRUDE\/CM.forest", "MIPK\/DORAS\/CRUDE\/CM.benign", "MIPK\/DORAS\/CRUDE\/CM.dunes", "MIPK\/DORAS\
"MIPK",
"MIPK\/CM.toroidal",
"MIPK\/CM.Supervoid",
"MIPK\/DORAS",
"MIPK\/DORAS\/CRUDE",
"MIPK\/DORAS\/CRUDE\/CM.forest",
"MIPK\/DORAS\/CRUDE\/CM.benign",
"MIPK\/DORAS\/CRUDE\/CM.dunes",
"MIPK\/DORAS\/COMMODITIES",
"MIPK\/DORAS\/COMMODITIES\/CRUDE",
"MIPK\/DORAS\/COMMODITIES\/CRUDE\/CM.tangeant",
"MIPK\/DORAS\/COMMODITIES\/CRUDE\/CM.astral",
"MIPK\/DORAS\/COMMODITIES\/CRUDE\/CM.forking"
目录用大写字母\/
分隔,混合大小写表示项目
我当前返回的JSon如下所示:
{
"contents": [{
"root_path": "MIPK",
"root_name": "MIPK",
"directories": [{
"subd_name": "DORAS",
"subd_path": "MIPK.DORAS"
}],
"views": [{
"view_name": "CM.toroidal"
},
{
"view_name": "CM.Supervoid"
}
]
}, {
"root_path": "MIPK.DORAS",
"root_name": "DORAS",
"directories": [{
"subd_name": "CRUDE",
"subd_path": "MIPK.DORAS.CRUDE"
},
{
"subd_name": "COMMODITIES",
"subd_path": "MIPK.DORAS.COMMODITIES"
}
],
"views": []
}, {
"root_path": "MIPK.DORAS.CRUDE",
"root_name": "CRUDE",
"directories": [],
"views": [{
"view_name": "CM.forest"
},
{
"view_name": "CM.benign"
},
{
"view_name": "CM.dunes"
}
]
}, {
"root_path": "MIPK.DORAS.COMMODITIES",
"root_name": "COMMODITIES",
"directories": [{
"subd_name": "CRUDE",
"subd_path": "MIPK.DORAS.COMMODITIES.CRUDE"
}],
"views": []
}, {
"root_path": "MIPK.DORAS.COMMODITIES.CRUDE",
"root_name": "CRUDE",
"directories": [],
"views": [{
"view_name": "CM.tangeant"
},
{
"view_name": "CM.astral"
},
{
"view_name": "CM.forking"
}
]
}]
}
当前代码:
import logging
import copy
import time
def fetch_resources(input_resources_list):
'''
:return: Json list of dictionaries each dictionary element containing:
Directory name, directory path, list of sub-directories, list of views
resource_list is a flattened list produced by a database walk function
'''
start = time.time()
resources = {
'contents': [{}]
}
for item in input_resources_list:
# Parsing list into usable pieces
components = item.rsplit('\\', 1)
if len(components) == 1:
# Handles first element
root_dict = {'root_path': components[0],
'root_name': components[-1],
'directories': [],
'views': []
}
resources['contents'][0].update(root_dict)
else:
# Enumerate resources in list so search by key value can be done and then records can be appended.
for ind, content in enumerate(copy.deepcopy(resources['contents'])):
if resources['contents'][ind]['root_path'] == components[0]:
# Directories are upper case, adds a new entry if
if clean_item.isupper() :
root_dict = {'root_path': components[0],
'root_name': components[-1],
'directories': [],
'views': []
}
resources['contents'].append(root_dict)
sub_dict = {'subd_path': components[0],
'subd_name': components[-1]}
resources['contents'][ind]['directories'].append(sub_dict)
elif clean_item.isupper() == False :
resources['contents'][ind]['views'] \
.append({'view_name':components[-1]})
print 'It took {}'.format((time.time() - start)*1000)
return resources
这在较小的工作负载(大约100-500)下可以正常工作,但在000的目标工作负载下则不行
根路径
键值进行搜索。有没有更简单的方法来搜索dict列表中的键值并将条目附加到条目目录和视图列表中在构建这些字符串时,您已经丢弃了很多信息。例如,当您看到
MIPK\/DORAS
时,无法知道它是文件(应该是父目录列表中的字符串)、叶目录(应该是父目录的dict中的列表)还是中间目录(应该是父目录的dict中的dict)。你能做的最好的事情(没有二次嵌套搜索)就是猜测,如果你猜错了,以后再修改它
此外,有时您的中间目录甚至不会单独显示,而只是作为后续路径的组件显示,但有时它们确实会显示。因此,有时您必须修复的“猜测”将是根本不存在的目录
最后,如果您想要的格式是不明确的,例如,任何直接包含文件和目录(应该是dict还是列表),或者什么都不包含(应该是空dict、空列表还是仅仅一个字符串?)
然而,事情似乎是有序的,模棱两可的情况似乎并没有真正出现。如果我们可以依赖这两个,我们可以通过查看某个东西是前缀还是下一个条目来判断它是否是目录。然后我们可以读取这些叶子,并将它们放入0个或多个嵌套dict中的列表中的字符串集合中
因此,首先,我们要迭代相邻的路径对,以便更容易地执行“它是下一个值的前缀吗?”检查:
output = {}
it1, it2 = itertools.tee(paths)
next(it2)
pairs = itertools.zip_longest(it1, it2, fillvalue='')
for path, nextpath in pairs:
if nextpath.startswith(path):
continue
现在,我们知道path
是一个叶子,因此我们需要找到要将其附加到的列表,如果需要,创建一个,这可能意味着一路上递归创建dict:
components = path.split(r'\/')
d = output
for component in components[:-2]:
d = d.setdefault(component, {})
d.setdefault(components[-2], []).append(components[-1])
我还没有对此进行测试,但是对于非歧义输入,它应该做正确的事情,但是如果任何目录同时包含文件和子目录,或者任何顶级目录包含文件,或者任何其他歧义情况(空目录除外,它将被视为与文件相同),则会引发某种异常
当然,这有点难看,但这是解析难看格式的固有特性,这种格式依赖于许多特殊的大小写规则来处理否则会产生歧义的内容。与其使用嵌套的理解,不如使用for循环语句来编写,这样可能就不会看起来那么凌乱,或者很难做到正确。并非所有内容都必须尽可能地密集。但与此同时,直接在漫游中生成所需内容可能会更容易,而不是使用漫游建立字符串列表,然后尝试解析这些字符串。此外,如果目录包含子目录,则将目录存储为dict,但如果它们包含文件,则作为列表。如果一个目录同时包含这两个内容,会发生什么情况?这是一个错误吗?作为对您上次评论的回应,它们可以包含文件和目录。。。向输出格式添加了说明。如果是这样的话,结构应该是什么样子?你已经完全改变了你所要求的结构。同时,你在这里展示的结构与你在评论我的答案时所要求的完全不同。无论您想要什么格式,您都可以使用我的答案中的基本结构进行构建,但当然有些细节会有所不同,我不能给您提供可以复制、粘贴和处理您可能要求的所有内容的代码。更新问题以更准确地反映我的要求。每个目录将包含以下字段:
名称
目录
视图
。其中目录包含子目录,视图只包含视图的id
。那么,字典将如何分配给这些标题呢?你能解释一下你提供的代码流程吗?我没听懂