如何匹配两对象数组指定键并返回符合要求的结构化结果
用户与赛事数据的匹配逻辑优化
数据定义
用户数据数组
const userData = [ { user_name: "Tania", email: "user-1@gmail.com", partido: "8", categoria_1: "1", categoria_2: "2", categoria_3: null }, { user_name: "Jean", email: "user-2@gmail.com", partido: "24", categoria_1: null, categoria_2: "2", categoria_3: null }, { user_name: "Vania", email: "user-4@gmail.com", partido: "13", categoria_1: null, categoria_2: "2", categoria_3: null }, { user_name: "Rick", email: "user-4@gmail.com", partido: "13", categoria_1: "1", categoria_2: "2", categoria_3: "3" } ];
赛事集合数据数组
(修正原代码语法错误:categoria_1: ""No dis"改为categoria_1: "No dis")
const collectionData = [ { partido: "8", Equipo_Local: "Argentina", Equipo_Visitante: "Arabia Saudí", categoria_1: "1", categoria_2: "No dis", categoria_3: "No dis" }, { partido: "24", Equipo_Local: "Argentina", Equipo_Visitante: "México", categoria_1: "No dis", categoria_2: "2", categoria_3: "No dis" }, { partido: "13", Equipo_Local: "Polonia", Equipo_Visitante: "Argentina", categoria_1: "No dis", categoria_2: "2", categoria_3: "3" } ];
数据特性
- 两个数组的所有对象均包含
partido、categoria_1、categoria_2、categoria_3属性,还可包含其他属性; - 上述属性值会动态变化。
现有匹配代码
现有代码尝试先按partido匹配,再依次匹配各分类,但输出不符合需求:
const checkPartido = ["partido"] const checkCategoria_1 = ["categoria_1"] const checkCategoria_2 = ["categoria_2"] const checkCategoria_3 = ["categoria_3"] function getMatches( first, second, checkPartido, checkCategoria_1, checkCategoria_2, checkCategoria_3) { let finalMatches = [] let matchPartido = [] let matchCat_1 = [] let matchCat_2 = [] let matchCat_3 = [] first.forEach((userMatch) => { second.forEach((collection) => { const isMatchPartido = checkPartido.every((key) => { return collection[key] === userMatch[key]; }); if ( isMatchPartido && !matchPartido.find((match) => match === userMatch) ) { matchPartido.push(userMatch); } }); }); matchPartido.forEach((userMatch) => { second.forEach((newCollection) => { const isMatchCategory = checkCategoria_1.every((key) => { return newCollection[key] === userMatch[key] }); if ( isMatchCategory && !matchCat_1.find((match) => { return match === userMatch }) ) { matchCat_1.push(userMatch) return matchCat_1 } }); }); matchCat_1.forEach((userMatch) => { second.forEach((newCollection) => { const isMatchCategory = checkCategoria_2.every((key) => { return newCollection[key] === userMatch[key] }); if ( isMatchCategory && !matchCat_2.find((match) => { return match === userMatch }) ) { matchCat_2.push(userMatch) return matchCat_2 } }); }); matchCat_2.forEach((userMatch) => { second.forEach((newCollection) => { const isMatchCategory = checkCategoria_3.every((key) => { return newCollection[key] === userMatch[key] }); if ( isMatchCategory && !matchCat_3.find((match) => { return match === userMatch }) ) { matchCat_3.push(userMatch) return matchCat_3 } }); }); return (finalMatches = [...matchCat_1, matchCat_2, matchCat_3]) } // 注:原调用函数名错误,应为getMatches console.log( getMatches( userData, collectionData, checkPartido, checkCategoria_1, checkCategoria_2, checkCategoria_3 ) )
预期匹配规则
- 对
partido: "8",匹配到1个用户(Tania),其categoria_1与赛事对应值匹配,返回包含该用户精简信息(user_name、email)的数组; - 对
partido: "24",匹配到1个用户(Jean),其categoria_2与赛事对应值匹配,返回对应精简数组; - 对
partido: "13",匹配到2个用户(Vania的categoria_2匹配,Rick的categoria_3匹配),返回对应精简对象数组。
解决方案
优化后的匹配函数
function getMatchedUsers(userData, collectionData) { // 将赛事数据按partido映射,提升查找效率 const collectionMap = new Map(); collectionData.forEach(item => { collectionMap.set(item.partido, item); }); // 按partido分组存储匹配的用户精简信息 const result = {}; userData.forEach(user => { const partido = user.partido; const collectionItem = collectionMap.get(partido); if (!collectionItem) return; // 检查是否有任意一个categoria匹配(用户值不为null且与赛事值相等) const isMatched = (user.categoria_1 !== null && user.categoria_1 === collectionItem.categoria_1) || (user.categoria_2 !== null && user.categoria_2 === collectionItem.categoria_2) || (user.categoria_3 !== null && user.categoria_3 === collectionItem.categoria_3); if (isMatched) { // 生成用户精简信息 const simplifiedUser = { user_name: user.user_name, email: user.email }; // 按partido分组添加结果 if (!result[partido]) { result[partido] = []; } result[partido].push(simplifiedUser); } }); return result; } // 调用函数并输出结果 console.log(getMatchedUsers(userData, collectionData));
输出结果
{ "8": [ { user_name: "Tania", email: "user-1@gmail.com" } ], "24": [ { user_name: "Jean", email: "user-2@gmail.com" } ], "13": [ { user_name: "Vania", email: "user-4@gmail.com" }, { user_name: "Rick", email: "user-4@gmail.com" } ] }
逻辑说明
- 赛事数据映射:用
Map存储赛事数据,避免嵌套循环查找,提升运行效率; - 匹配逻辑:对每个用户,先找到对应
partido的赛事项,只要用户的某一categoria值不为null且与赛事对应值相等,即判定为匹配; - 结果分组:按
partido分组存储匹配的用户精简信息,完全符合预期输出结构; - 精简信息:只保留
user_name和email字段,满足需求中的精简要求。
内容的提问来源于stack exchange,提问作者Omar Giancarlo
相关产品推荐
相关产品推荐

