0

0

高效合并 JavaScript 对象数组:以键为基准的聚合方法

心靈之曲

心靈之曲

发布时间:2025-10-01 09:48:11

|

784人浏览过

|

来源于php中文网

原创

高效合并 JavaScript 对象数组:以键为基准的聚合方法

本教程详细阐述了如何在 JavaScript 中高效地将包含不同结构但共享同一逻辑键的 JSON 对象数组进行合并。通过利用 Array.prototype.reduce() 和 Object.assign(),文章提供了一种简洁而强大的方法,将散布的数据聚合为结构完整、易于处理的单个对象,从而简化数据管理和后续操作。

引言:数据合并的挑战

在处理复杂数据时,我们经常会遇到需要将分散在不同对象中的相关信息聚合到一起的场景。例如,你可能有一个包含学生基本信息的对象,以及另一个包含学生保密数据的对象,它们通过一个共同的 key(如学生id)关联。目标是将这些信息合并成一个统一的学生记录,以便于管理和展示。

考虑以下原始数据结构:

[
  {
    "key": 111,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ]
  },
  {
    "key": 222,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ]
  },
  {
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 111
    }
  },
  {
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 222
    }
  }
]

我们期望的输出是这样的,每个 key 对应的所有信息都被合并到一个对象中:

[
  {
    "key": 111,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ],
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 111
    }
  },
  {
    "key": 222,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ],
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 222
    }
  }
]

核心合并策略:reduce 与 Object.assign

JavaScript 提供了强大的数组和对象操作方法,其中 Array.prototype.reduce() 和 Object.assign() 在处理这类数据聚合任务时尤为高效和灵活。

  • Array.prototype.reduce(): 这个方法对数组中的每个元素执行一个由您提供的 reducer 函数,将其结果汇总为单个返回值。它非常适合用于构建一个新数组或新对象,通过迭代原始数组来逐步填充。
  • Object.assign(): 这个方法用于将所有可枚举的自有属性从一个或多个源对象复制到目标对象。它会返回目标对象。当属性名相同时,后面的源对象的属性会覆盖前面源对象的属性。

结合这两个方法,我们可以遍历原始数据数组,根据对象的 key 识别并合并相关信息。

立即学习Java免费学习笔记(深入)”;

基于VC与Matlab的混合编程实现图像的三维显示 WORD版
基于VC与Matlab的混合编程实现图像的三维显示 WORD版

本文档主要讲述的是基于VC与Matlab的混合编程实现图像的三维显示;介绍了VC++与Matlab混合编程的一般实现方法,并实现对二维影像图的三维效果显示。 MATLAB既是一种直观、高效的计算机语言,同时又是一个科学计算平台。它为数据分析和数据可视化、算法和应用程序开发提供了最核心的数学和高级图形工具。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看

下载

解决方案与代码示例

以下代码展示了如何使用 reduce 和 Object.assign 来实现上述数据合并:

const inputData = [
  {
    key: 111,
    studentInfo: [
      {
        details: {
          calculated_fields: null,
          status: false,
        },
      },
    ],
  },
  {
    key: 222,
    studentInfo: [
      {
        details: {
          calculated_fields: null,
          status: false,
        },
      },
    ],
  },
  {
    confidential: {
      data: {
        access_control: {
          private_data: null,
          users: [],
        },
      },
      key: 111,
    },
  },
  {
    confidential: {
      data: {
        access_control: {
          private_data: null,
          users: [],
        },
      },
      key: 222,
    },
  },
];

const mergedResult = []; // 声明一个空数组,作为 reduce 的累加器初始值

inputData.reduce((outputAccumulator, currentObject) => {
  // 判断当前对象是否包含顶层的 'key' 属性
  if (currentObject.key) {
    // 如果有顶层 'key',我们将其视为该键的“主记录”或起始记录,
    // 直接推入结果数组中。
    outputAccumulator.push(currentObject);
  } else {
    // 如果没有顶层 'key',则认为其 'key' 嵌套在 'confidential' 属性中,
    // 并且该对象是用于补充现有记录的“辅助记录”。
    // 查找 outputAccumulator 中是否存在与当前对象的 confidential.key 匹配的记录。
    const targetObject = outputAccumulator.find(
      (o) => o.key === currentObject.confidential.key
    );

    // 如果找到了匹配的目标对象,则将当前对象的属性合并到目标对象中。
    // Object.assign 会将 currentObject 的所有可枚举属性复制到 targetObject。
    // 如果属性名冲突,currentObject 的值将覆盖 targetObject 的值。
    if (targetObject) {
      Object.assign(targetObject, currentObject);
    }
  }
  // 返回累加器,供下一次迭代使用
  return outputAccumulator;
}, mergedResult); // 将 mergedResult 作为 reduce 的初始累加器

console.log(JSON.stringify(mergedResult, null, 2));

代码解析

  1. mergedResult = []: 我们初始化一个空数组 mergedResult,它将作为 reduce 方法的累加器 (outputAccumulator),最终包含所有合并后的对象。
  2. inputData.reduce((outputAccumulator, currentObject) => { ... }, mergedResult):
    • reduce 方法遍历 inputData 数组中的每一个 currentObject。
    • 在每次迭代中,它会执行回调函数,并将上一次迭代返回的 outputAccumulator 和当前的 currentObject 作为参数传入。
  3. if (currentObject.key): 这是一个关键的判断。它区分了两种类型的对象:
    • 主记录: 如果 currentObject 拥有顶层 key 属性(例如 studentInfo 对象),它被视为该键的“主记录”。我们直接将其推入 outputAccumulator。
    • 辅助记录: 如果 currentObject 没有顶层 key 属性(例如 confidential 对象),我们假设它的 key 嵌套在 confidential.key 中,并且它旨在补充一个已存在的主记录。
  4. outputAccumulator.find((o) => o.key === currentObject.confidential.key): 对于辅助记录,我们使用 find 方法在 outputAccumulator 中查找一个已经存在的主记录,该主记录的 key 与当前辅助记录的 confidential.key 相匹配。
  5. Object.assign(targetObject, currentObject): 如果找到了匹配的 targetObject,我们就使用 Object.assign 将 currentObject 的所有属性合并到 targetObject 中。这样,targetObject 就会被 currentObject 的新属性所扩展,从而实现了数据的聚合。
  6. return outputAccumulator: 每次迭代结束后,回调函数返回当前的 outputAccumulator,它将作为下一次迭代的 outputAccumulator。

注意事项

  • 键的唯一性与一致性: 确保用于合并的键(无论是顶层 key 还是嵌套的 confidential.key)在逻辑上是唯一的,并且在所有相关对象中保持一致。如果键值不唯一,合并结果可能不符合预期。
  • 属性覆盖行为: Object.assign() 在合并时,如果源对象和目标对象有相同的属性名,源对象的属性值会覆盖目标对象的属性值。在设计数据结构时,需要考虑这种覆盖行为是否符合您的业务逻辑。如果需要更复杂的合并策略(例如深度合并、数组合并等),可能需要使用 Lodash 库的 _.merge 或自定义合并函数。
  • 性能考量: 对于非常庞大的数组(例如数十万条记录),find 方法在每次迭代中都会遍历 outputAccumulator,这可能导致性能下降(O(N^2) 复杂度)。在这种情况下,可以考虑使用 Map 或 Object 作为中间存储来优化查找过程,将时间复杂度降低到 O(N)。 例如,先将所有对象按键存储到 Map 中:
    const map = new Map();
    inputData.forEach(obj => {
        const key = obj.key || obj.confidential?.key;
        if (key) {
            map.set(key, { ...(map.get(key) || {}), ...obj });
        }
    });
    const optimizedMergedResult = Array.from(map.values());

    这种方式通常在处理大规模数据时表现更优。

  • 键的嵌套深度: 本教程的解决方案假设 key 要么在顶层,要么直接嵌套在 confidential 属性下。如果 key 可能出现在更深的嵌套层级或不同的路径下,则需要调整查找 key 的逻辑,使其更具通用性。

总结

通过巧妙地结合 Array.prototype.reduce() 和 Object.assign(),我们能够以一种声明式且高效的方式,将结构不一致但通过共同键关联的 JSON 对象数组进行合并。这种模式在数据预处理、API响应整合以及各种需要数据聚合的场景中都非常实用。理解其背后的原理和注意事项,有助于开发者构建更健壮、更高效的数据处理逻辑。

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

540

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

372

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

727

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

470

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

391

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

990

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

653

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

543

2023.09.20

桌面文件位置介绍
桌面文件位置介绍

本专题整合了桌面文件相关教程,阅读专题下面的文章了解更多内容。

0

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.1万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 1.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号