如何基于相同键值合并对象数组,多匹配时按优先级合并(JS)
在JavaScript中按指定优先级合并对象数组
需求说明
基于对象数组的相同键值(数组a的x与数组b的x1)合并两个对象数组;当存在多个匹配项时,按照给定的priority数组规则选择最高优先级的项完成合并。
示例数据
数组a(x值唯一)
const a = [ { x: 'all', y: 'tablename', z: 'schema' }, { x: 'all1', y: 'tablename', z: 'schema' }, { x: 'all2', y: 'tablename', z: 'schema' }, { x: 'al52', y: 'tablename', z: 'schema' }, ];
数组b
const b = [ { x1: 'all', y1: 'tablename', z1: 'schema' }, { x1: 'all', y1: 'tablename1', z1: 'schema1' }, { x1: 'all1', y1: 'tablename1', z1: 'schema1' }, { x1: 'all', y1: 'tablename3', z1: 'schema' }, { x1: 'all1', y1: 'tablename2', z1: 'schema1' }, ];
优先级规则数组priority
优先级从高到低排列,匹配时优先选择排在前面的项:
const priority = [ { y1: 'tablename3', z1: 'schema' }, { y1: 'tablename1', z1: 'schema1' }, { y1: 'tablename2', z1: 'schema' }, { y1: 'tablename', z1: 'schema' }, ];
预期合并结果
const expected = [ { x: 'all', y: 'tablename', z: 'schema', x1: 'all', y1: 'tablename3', z1: 'schema', }, { x: 'all1', y: 'tablename1', z: 'schema1', x1: 'all1', y1: 'tablename1', z1: 'schema1', }, ];
当前问题
现有代码仅匹配到第一个符合x === x1的项就停止遍历,未按照优先级规则筛选最优项,导致输出结果不符合预期:
实际输出结果
const actual = [ { x: 'all', x1: 'all', y: 'tablename', y1: 'tablename', z: 'schema', z1: 'schema', }, { x: 'all1', x1: 'all1', y: 'tablename', y1: 'tablename1', z: 'schema', z1: 'schema1', }, ];
现有代码
var c = []; for (var i = 0; i < a.length; i++) { for (var j = 0; j < b.length; j++) { if (a[i].x === b[j].x1) { var combinedObj = { x: a[i].x, y: a[i].y, z: a[i].z, x1: b[j].x1, y1: b[j].y1, z1: b[j].z1, }; c.push(combinedObj); break; } } } console.log(c);
修改方案
核心思路是先为优先级规则建立快速查找的映射,再对每个a的项筛选所有匹配的b项,最后选出优先级最高的项完成合并(从预期结果看,合并时a的y、z需要替换为选中b项的y1、z1)。
修改后的代码
// 1. 建立优先级映射:将{y1,z1}组合映射为优先级分数(分数越高优先级越高) const priorityMap = new Map(); priority.forEach((item, index) => { const key = `${item.y1}-${item.z1}`; // 用数组长度减去索引值作为分数,越靠前的项分数越高 priorityMap.set(key, priority.length - index); }); const result = []; // 2. 遍历数组a的每个项 for (const itemA of a) { // 筛选出b中所有x1与itemA.x匹配的项 const matchedItems = b.filter(itemB => itemB.x1 === itemA.x); // 无匹配项则跳过(按预期结果只保留有匹配的项) if (matchedItems.length === 0) continue; // 3. 从匹配项中选出优先级最高的项 const highestPriorityItem = matchedItems.reduce((prev, curr) => { const prevKey = `${prev.y1}-${prev.z1}`; const currKey = `${curr.y1}-${curr.z1}`; return priorityMap.get(prevKey) > priorityMap.get(currKey) ? prev : curr; }); // 4. 合并对象:保留a的x,替换y、z为b的y1、z1,同时加入b的所有字段 const merged = { x: itemA.x, y: highestPriorityItem.y1, z: highestPriorityItem.z1, x1: highestPriorityItem.x1, y1: highestPriorityItem.y1, z1: highestPriorityItem.z1, }; result.push(merged); } console.log(result);
代码说明
- 优先级映射:把
priority数组中的每个{y1,z1}组合转换为唯一键,用反向索引值作为优先级分数,实现快速的优先级比较。 - 筛选匹配项:对每个
a的项,找出所有b中x1匹配的项,避免只取第一个匹配项的问题。 - 选择最优项:通过
reduce遍历匹配项,选出优先级分数最高的项。 - 合并对象:按照预期结果的格式,完成对象合并并加入结果数组。
内容的提问来源于stack exchange,提问作者Suparna
相关产品推荐
相关产品推荐

