如何用Underscore.js基于user_id而非索引合并JavaScript数组对象?
根据
user_id合并两个JavaScript数组的方案 这需求我做项目时经常碰到,核心就是靠user_id这个唯一标识来匹配两个数组里的对象,再把它们的属性合并到一起。下面给你两种高效又易读的实现方式:
方法一:用reduce创建映射表(最常用)
先把其中一个数组转成以user_id为键的对象,这样后续查找匹配项的速度会非常快,接着遍历另一个数组完成合并:
const array1 = [{ "name": "Smart Test Pool", "user_id": 1, "total_time": "15.0" }]; const array2 = [{ "user_id": 1, "total_hours_worked_milliseconds": 60060000, "total_time_unshedule_milliseconds": 540000 }]; // 把array1转成以user_id为key的对象 const mergedMap = array1.reduce((map, item) => { map[item.user_id] = item; return map; }, {}); // 遍历array2,把属性合并到对应的对象里 array2.forEach(item => { if (mergedMap[item.user_id]) { // 用展开语法合并属性,也可以用Object.assign mergedMap[item.user_id] = { ...mergedMap[item.user_id], ...item }; } }); // 把映射表转回数组,就是最终结果 const result = Object.values(mergedMap); console.log(result);
方法二:用ES6 Map结构(更直观)
Map的键可以是任意类型,用它存储以user_id为标识的对象,逻辑和上面类似,但可读性更强:
const array1 = [{ "name": "Smart Test Pool", "user_id": 1, "total_time": "15.0" }]; const array2 = [{ "user_id": 1, "total_hours_worked_milliseconds": 60060000, "total_time_unshedule_milliseconds": 540000 }]; const userMap = new Map(); // 先把array1的元素存入Map array1.forEach(item => { userMap.set(item.user_id, item); }); // 遍历array2合并属性 array2.forEach(item => { const existingItem = userMap.get(item.user_id); if (existingItem) { userMap.set(item.user_id, { ...existingItem, ...item }); } else { // 如果array2里有array1没有的user_id,也可以直接添加进去 userMap.set(item.user_id, item); } }); // 转成数组 const result = Array.from(userMap.values()); console.log(result);
额外说明
- 这两种方法的时间复杂度都是
O(n + m)(n、m分别是两个数组的长度),比嵌套循环的O(n*m)高效很多,数组越大优势越明显。 - 如果数组里存在重复的
user_id(比如array1里有多个同user_id的对象),上面的代码会保留最后一个匹配项,要是需要处理这种场景,可以在reduce或forEach里调整逻辑(比如合并数组而非直接覆盖)。
运行代码后,你就能得到期望的结果:
[{ "name": "Smart Test Pool", "user_id": 1, "total_time": "15.0", "total_hours_worked_milliseconds": 60060000, "total_time_unshedule_milliseconds": 540000 }]
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

