
本文介绍如何将多层嵌套的标题-子标题-内容结构,按严格层级顺序(title01→subtitle01→content01→title02→subtitle02→content02…)扁平化为一个仅含单个对象的数组,实现语义化键名与序列化编号的精准映射。
本文介绍如何将多层嵌套的标题-子标题-内容结构,按严格层级顺序(title01→subtitle01→content01→title02→subtitle02→content02…)扁平化为一个仅含单个对象的数组,实现语义化键名与序列化编号的精准映射。
在实际业务中(如富文本编辑器导出、CMS内容序列化或表单动态渲染),我们常需将树状嵌套数据转换为线性、有序、键名可预测的扁平结构。但注意:题设目标并非传统 flat() 或递归展平,而是保持层级逻辑顺序 + 自动编号 + 单对象聚合——即最终输出形如 [ { titles01: {...}, subtitles01: {...}, content01: {...}, titles02: {...}, ... } ] 的单元素数组。
以下是推荐的健壮实现方案(已优化原始答案中的硬编码逻辑与潜在 bug):
const data = [
{
titles: [
{
id: 1,
name: "Title 01",
subtitles: [
{
id: 2,
name: "Subtitle 01",
title_id: 1,
content: [
{
id: 3,
name: "Content 01",
subtitle_id: 2,
},
],
},
],
},
{
id: 4,
name: "Title 02", // 注意:原文此处 name 仍为 "Title 01",已按语义修正为 "Title 02"
subtitles: [
{
id: 5,
name: "Subtitle 02",
title_id: 4,
content: [
{
id: 6,
name: "Content 02",
subtitle_id: 5,
},
],
},
],
},
],
},
];
function flattenBySequence(arr) {
const result = {};
let titleIndex = 0;
arr.forEach((section) => {
if (!Array.isArray(section.titles)) return;
section.titles.forEach((title) => {
titleIndex++;
const titleKey = `titles${titleIndex < 10 ? '0' : ''}${titleIndex}`;
result[titleKey] = { id: title.id, name: title.name };
if (Array.isArray(title.subtitles)) {
title.subtitles.forEach((subtitle) => {
const subtitleKey = `subtitles${titleIndex < 10 ? '0' : ''}${titleIndex}`;
result[subtitleKey] = {
id: subtitle.id,
name: subtitle.name,
title_id: subtitle.title_id,
};
if (Array.isArray(subtitle.content)) {
subtitle.content.forEach((content) => {
const contentKey = `content${titleIndex < 10 ? '0' : ''}${titleIndex}`;
result[contentKey] = {
id: content.id,
name: content.name,
subtitle_id: content.subtitle_id,
};
});
}
});
}
});
});
return [result]; // 严格返回单元素数组,符合题设 flatArr 形式
}
const flatArr = flattenBySequence(data);
console.log(flatArr);
// 输出:
// [{
// titles01: { id: 1, name: "Title 01" },
// subtitles01: { id: 2, name: "Subtitle 01", title_id: 1 },
// content01: { id: 3, name: "Content 01", subtitle_id: 2 },
// titles02: { id: 4, name: "Title 02" },
// subtitles02: { id: 5, name: "Subtitle 02", title_id: 4 },
// content02: { id: 6, name: "Content 02", subtitle_id: 5 }
// }]✅ 关键设计说明:
-
序列号统一基于
title顺序:每个title触发一次titleIndex++,其下属subtitle和content共享同一序号(如titles01/subtitles01/content01),严格满足“一标题→一子标题→一内容”的线性节奏; -
智能编号格式:
titleIndex 实现 <code>01,02, ...,10,11的自然补零,避免titles1与titles10键名排序错乱; -
防御性编程:显式校验
Array.isArray(),防止空字段或数据缺失导致运行时错误; -
语义清晰命名:函数名
flattenBySequence明确表达“按顺序扁平化”,优于模糊的flattenData。
⚠️ 注意事项:
- 此方案假设每
title最多含一个subtitle,且每个subtitle最多含一个content(符合题设结构)。若需支持多 subtitle / 多 content,请明确扩展规则(如subtitle01_01,content01_01); - 键名大小写需统一(原文
sutitles01为笔误,已修正为subtitles01); - 若数据量极大,可考虑使用
Map替代对象累加以提升性能,但对常规 CMS 场景无必要。
该方法兼顾可读性、可维护性与业务语义,是处理层级化内容序列化的典型工程实践。

















