Node.js中基于不同字段比较对象数组的更优方案问询
在Node.js中基于不同属性匹配合并对象数组的最优方案
现有两个对象数组,需要基于名称不同的属性(如obj1的field1对应obj2的attribute1)进行匹配并合并对象。当前采用双重循环实现,但希望找到无需双重循环、更高效或借助第三方包的优化方案。
原实现代码如下:
let obj1 = [{field1:11, field2:12, field3:13}, {field1:21, field2:22, field3:23}, {field1:31, field2:32, field3:33}, {field1:41, field2:42, field3:43}]; let obj2 = [{attribute1:21, attribute2:22}, {attribute1:31, attribute2:32}, {attribute1:11, attribute2:12}]; let output = []; obj1.map(o1 => { for (let i=0;i<obj2.length;i++) { if (o1.field1 === obj2[i].attribute1) { output.push(Object.assign(obj2[i], o1)); obj2.splice(i,1); break; } } }); console.log(output); // 输出: [{attribute1:11,attribute2:12,field1:11,field2:12,field3:13},{attribute1:21,attribute2:22,field1:21,field2:22,field3:23},{attribute1:31,attribute2:32,field1:31,field2:32,field3:33}]
方案一:原生Map实现(无第三方依赖,O(n+m)时间复杂度)
通过将其中一个数组转换为Map结构,把匹配字段的值作为key,对象本身作为value,后续查找匹配项的时间复杂度降为O(1),整体效率远高于双重循环,同时避免修改原数组:
let obj1 = [{field1:11, field2:12, field3:13}, {field1:21, field2:22, field3:23}, {field1:31, field2:32, field3:33}, {field1:41, field2:42, field3:43}]; let obj2 = [{attribute1:21, attribute2:22}, {attribute1:31, attribute2:32}, {attribute1:11, attribute2:12}]; // 将obj2转换为Map,key为attribute1的值 const obj2Map = new Map(obj2.map(item => [item.attribute1, item])); // 遍历obj1,匹配并合并 const output = obj1 .map(o1 => { const matched = obj2Map.get(o1.field1); return matched ? {...matched, ...o1} : null; }) .filter(item => item !== null); // 过滤掉无匹配的项 console.log(output);
核心优势:
- 原生JS实现,无需额外依赖
- 时间复杂度从O(n*m)降至O(n+m),数据量大时性能提升明显
- 不修改原数组,避免副作用
方案二:使用Lodash简化实现
如果项目中已引入Lodash,可利用其keyBy和map方法快速实现,代码更简洁:
const _ = require('lodash'); let obj1 = [{field1:11, field2:12, field3:13}, {field1:21, field2:22, field3:23}, {field1:31, field2:32, field3:33}, {field1:41, field2:42, field3:43}]; let obj2 = [{attribute1:21, attribute2:22}, {attribute1:31, attribute2:32}, {attribute1:11, attribute2:12}]; // 按attribute1分组obj2 const obj2Grouped = _.keyBy(obj2, 'attribute1'); // 遍历obj1匹配合并 const output = _.compact( _.map(obj1, o1 => { const matched = obj2Grouped[o1.field1]; return matched ? _.merge({}, matched, o1) : null; }) ); console.log(output);
核心优势:
- 代码简洁易读,减少手动实现成本
- Lodash的
merge方法支持复杂嵌套对象的合并,适配更多场景 compact方法自动过滤null/undefined项
方案三:多属性匹配扩展
如果需要基于多个不同属性匹配,只需调整Map的key生成方式,用多个属性值拼接成唯一key即可:
let obj1 = [{field1:11, field2:12, field3:13}, {field1:21, field2:22, field3:23}]; let obj2 = [{attribute1:21, attribute2:22}, {attribute1:11, attribute2:12}]; // 基于两个属性生成唯一key const obj2Map = new Map(obj2.map(item => [`${item.attribute1}-${item.attribute2}`, item])); const output = obj1 .map(o1 => { const key = `${o1.field1}-${o1.field2}`; const matched = obj2Map.get(key); return matched ? {...matched, ...o1} : null; }) .filter(Boolean); console.log(output);
内容的提问来源于stack exchange,提问作者Vishal Gupta
相关产品推荐
相关产品推荐

