JavaScript实现:将路径列表转为类字典嵌套对象的问题
问题:将路径列表转换为嵌套对象结构
我有如下路径列表:
[ "posts/index/cms.md", "posts/index/test/sidegenerator.md", "posts/ssg/gatsby.md", "posts/ssg/hugo.md", "posts/ssg/generator/rt/gen.txt", "example/test.md" ]
想要转换为嵌套对象结构:
{ "posts": { "index": { "cms.md": null, "test": { "sidegenerator.md": null } }, "ssg": { "gatsby.md": null, "hugo.md": null, "generator": { "rt": { "gen.txt": null } } } }, "example": { "test.md": null } }
我有Python背景,知道JavaScript中没有字典,只有具备类字典功能的Object(键值对形式)。自己编写了递归函数,但遇到对象引用问题,无法给已有对象添加新键,现有代码及输出如下:
现有代码
辅助函数
function create_dict_outof_list(index, rest_of_list){ if (index == rest_of_list.length-1){ return rest_of_list[index] }else { let new_dict = {} new_dict[rest_of_list[index]] = create_dict_outof_list(index+1, rest_of_list) return new_dict } }
递归生成函数
function recursive_dict_generator(data_dict, index, list){ console.log("Dict: ", list[index] in data_dict) if (index < list.length-1){ if (list[index] in data_dict){ return data_dict[list[index]] = recursive_dict_generator(data_dict[list[index]], index+1, list) } else { return data_dict[list[index]] = create_dict_outof_list(0, list.slice(index)) } } else { if (list[index] in data_dict){ return data_dict } else { return list[index] } } }
测试主函数
function main(){ let data_dict = {} let new_dict = {} new_dict = recursive_dict_generator(data_dict, 0, ["posts","index", "test", "sidegenerator.md"]) console.log("test 1: ", data_dict) console.log("test 1.5", new_dict) recursive_dict_generator(data_dict, 0, ["posts","ssg", "generator", "rt", "test.md"]) console.log("test 2: ", data_dict) }
控制台输出
test 1: { posts: { posts: { index: [Object] } } } test 1.5 { posts: { index: { test: 'sidegenerator.md' } } } test 2: { posts: { ssg: { generator: [Object] } } }
解决方案
你的代码核心问题有两个:
create_dict_outof_list调用时传入list.slice(index)后从索引0开始递归,导致重复创建外层键(比如第一次测试里的posts被重复嵌套)。- 处理文件片段时,直接返回文件名而非给当前对象赋值
null,且已有键存在时的逻辑不符合需求。
可以简化逻辑,用单循环+对象引用追踪就能完成,无需拆分多个递归函数:
function buildNestedStructure(paths) { const result = {}; paths.forEach(path => { const segments = path.split('/'); let current = result; for (let i = 0; i < segments.length; i++) { const segment = segments[i]; // 最后一段是文件,直接赋值为null if (i === segments.length - 1) { current[segment] = null; } else { // 当前层级无该键则创建空对象 if (!current[segment]) { current[segment] = {}; } // 切换到下一层级对象 current = current[segment]; } } }); return result; } // 测试用例 const paths = [ "posts/index/cms.md", "posts/index/test/sidegenerator.md", "posts/ssg/gatsby.md", "posts/ssg/hugo.md", "posts/ssg/generator/rt/gen.txt", "example/test.md" ]; console.log(JSON.stringify(buildNestedStructure(paths), null, 2));
代码说明
- 遍历每个路径,用
split('/')拆分成路径片段数组。 - 用
current变量追踪当前操作的层级对象,初始指向根对象result。 - 循环处理每个片段:
- 如果是最后一个片段(文件名),直接给当前对象的对应键赋值
null。 - 如果是目录片段,检查当前对象是否已有该键,没有则创建空对象,然后将
current切换到这个子对象,继续处理下一层。
- 如果是最后一个片段(文件名),直接给当前对象的对应键赋值
这种方式能正确复用已有对象的引用,不会覆盖或重复创建键,最终生成目标嵌套结构。
内容的提问来源于stack exchange,提问作者Luca Moser
相关产品推荐
相关产品推荐

