如何在JavaScript中递归归并结构对称的对象数组?
递归归并对称结构化数据的实现方案
需求说明
需要将一组结构对称的嵌套数据递归归并,把相同层级同key的零散值收集到数组中,深层嵌套结构保持对应层级的归并逻辑。
原始输入数据
const data = [ { name: 'Bob', relations: { siblings: [ { name: 'Tom', age: '20', snacks: [ { type: 'yogurt' } ] }, { name: 'Jacob', snacks: [ { type: 'cookie', amount: '2' }, { type: 'brownie', amount: '3' } ] } ] } }, { name: 'Robert', relations: { siblings: [ { name: 'Timmy', age: '16', snacks: [ { type: 'fudge' }, { type: 'brownie' } ] } ] } } ];
期望输出结果
const output = { name: ['Bob', 'Robert'], relations: { siblings: { name: ['Tom', 'Jacob', 'Timmy'], age: ['20', '16'], snacks: { type: ['yogurt', 'cookie', 'fudge', 'brownie'], amount: ['2', '3'] } } } }
现有代码问题
你写的compact函数存在几个核心问题:
- 参数引用错误:函数参数是
value,但内部误用了未定义的object变量 - 完全跳过数组的递归处理逻辑,无法处理数组类型的嵌套结构
- 没有实现值的合并逻辑,仅简单覆盖累计对象的key,无法收集多个同key的值
- 原始类型的处理逻辑错误,没有将值正确收集到数组中
修改后的递归实现代码
const mergeData = (input, accumulator = {}) => { // 处理数组:遍历每个元素递归合并 if (Array.isArray(input)) { return input.reduce((acc, item) => mergeData(item, acc), accumulator); } // 处理原始类型(字符串、数字等):收集到数组并去重 if (typeof input !== 'object' || input === null) { return Array.isArray(accumulator) ? [...new Set([...accumulator, input])] : [input]; } // 处理对象:遍历每个键值对递归合并 return Object.entries(input).reduce((acc, [key, value]) => { // 递归处理当前值,并合并到累计器的对应key中 acc[key] = mergeData(value, acc[key]); return acc; }, accumulator); }; // 使用示例 const output = mergeData(data); console.log(output);
代码逻辑解释
- 数组处理分支:如果输入是数组,用
reduce遍历每个元素,将当前元素和累计器传入递归函数,实现逐个元素的归并 - 原始类型处理分支:如果输入是字符串、数字等原始类型,将其添加到数组中,用
Set去重(匹配你期望输出中重复brownie只保留一次的需求);若累计器已有对应数组,则合并后去重,否则直接生成新数组 - 对象处理分支:遍历对象的每个键值对,递归处理当前值,并将结果合并到累计器的对应key中,实现深层嵌套结构的归并
- 累计器传递:通过第二个参数
accumulator在递归过程中传递已合并的结果,避免重复创建对象,实现逐步合并
内容的提问来源于stack exchange,提问作者Tim Elton
相关产品推荐
相关产品推荐

