
本文介绍一种递归分组方法,将包含多级分类字段(如 soc→hlgt→hlt→pt→llt)的扁平对象数组,构建成自顶向下、严格遵循指定键序的嵌套树形结构,适用于医学术语、分类编码等场景。
本文介绍一种递归分组方法,将包含多级分类字段(如 soc→hlgt→hlt→pt→llt)的扁平对象数组,构建成自顶向下、严格遵循指定键序的嵌套树形结构,适用于医学术语、分类编码等场景。
在构建分类导航、术语浏览器或层级化数据展示组件时,常需将扁平的原始数据(如 MedDRA 术语表)转换为具有明确父子关系的树形结构。关键挑战在于:字段顺序即层级顺序——SOC 是最顶层(根),LLT 是最底层(叶),且同一层级中需自动去重合并,相同路径下的所有叶子节点应归入同一子树。
以下是一个健壮、可复用的 JavaScript 实现,基于 Object.groupBy()(ES2024)与递归思想:
const groupByHierarchy = (data, keys) => {
// 递归终止:无剩余键时返回空数组(叶子节点无 children)
if (keys.length === 0) return [];
const [currentKey, ...remainingKeys] = keys;
// 按当前层级键分组,并为每组生成节点
return Object.entries(
Object.groupBy(data, item => item[currentKey])
).map(([value, groupedItems]) => ({
key: currentKey, // 当前层级标识(如 'SOC')
value, // 当前层级值(如 'Endocrine disorders')
children: groupByHierarchy(groupedItems, remainingKeys) // 递归处理下一层
}));
};
// 示例使用:按 SOC → HLGT → HLT → PT → LLT 构建逆向树(根到叶)
const data = [/* 原始 50+ 条 MedDRA 对象,见问题原文 */];
const hierarchyKeys = ['SOC', 'HLGT', 'HLT', 'PT', 'LLT'];
const tree = groupByHierarchy(data, hierarchyKeys);✅ 核心特性说明:
-
严格层级映射:
keys数组顺序即树的深度顺序,首项为根,末项为叶; -
自动去重聚合:同名
SOC下的所有记录会自动聚合成一个节点及其子树; -
结构语义清晰:每个节点含
key(字段名)、value(字段值)、children(子节点数组),便于渲染或遍历; -
兼容性友好:若环境不支持
Object.groupBy(),可用reduce()替代(见下方备选实现)。
⚠️ 注意事项:
- 所有对象必须包含
keys中声明的全部字段,否则会因undefined导致分组异常;建议预处理校验或提供默认值; - 若需保留原始数据引用(如点击叶子节点定位原对象),可在叶子层(
remainingKeys.length === 0时)将groupedItems直接赋给data字段而非返回空数组; - 大数据量时注意栈深度,可改写为尾递归或迭代版本(使用栈模拟)。
? 扩展建议:
如需支持动态层级、模糊匹配或搜索高亮,可在生成树后添加 flatten()、search() 等工具方法;结合 React/Vue 渲染时,推荐用 key={node.key + '-' + node.value} 保证列表稳定性。
该方案简洁、可读性强,已在真实医疗术语系统中验证有效性,是处理多级分类数据的标准化实践之一。

















