JavaScript 实现对象数组多条件过滤及匹配度降序排序
实现目标过滤排序效果的方案
核心逻辑说明
你当前编写的基础过滤逻辑是正确的——只要对象包含至少一个目标维生素就会被保留,缺失的核心环节是基于匹配维生素数量的降序排序,当前输出保持了fruits数组的原始顺序,没有按照匹配数重新排列。
排序的核心规则为:统计每个水果对象与vitaminsArray的匹配元素总数,数值越高排序越靠前。
代码实现
直观基础版(适合小数据量场景)
// 计算单个水果与目标维生素数组的匹配数量 const getMatchCount = (fruit, targetVitamins) => { return targetVitamins.reduce((count, vitamin) => { return fruit.vitamins.includes(vitamin) ? count + 1 : count; }, 0) } function filterAndSort(vitaminsArray) { return fruits // 保留至少命中一个目标维生素的对象 .filter(fruit => fruit.vitamins.some(vitamin => vitaminsArray.includes(vitamin))) // 按匹配数量降序排序 .sort((itemA, itemB) => { const countA = getMatchCount(itemA, vitaminsArray); const countB = getMatchCount(itemB, vitaminsArray); return countB - countA; }) }
性能优化版(适合大数据量场景)
基础版中sort的比较函数会被多次触发,每次触发都会重复计算两个对象的匹配数,存在冗余开销。优化方案为在遍历阶段提前计算好每个对象的匹配数,避免重复计算:
function filterAndSort(vitaminsArray) { return fruits // 第一次遍历:提前计算每个对象的匹配数 .map(fruit => ({ ...fruit, matchCount: vitaminsArray.reduce((count, vitamin) => { return fruit.vitamins.includes(vitamin) ? count + 1 : count; }, 0) })) // 过滤掉无任何匹配的对象 .filter(item => item.matchCount > 0) // 直接使用预存的匹配数排序 .sort((a, b) => b.matchCount - a.matchCount) // 移除临时存储的匹配数字段,保持原数据结构输出 .map(({matchCount, ...originalFruit}) => originalFruit) }
输出效果校验
两种实现的输出结果完全匹配预期:
apple匹配数为3(三个目标维生素全部命中) → 排第一位banana匹配数为2(命中Vitamin_C2、Vitamin_B) → 排第二位orange匹配数为1(仅命中Vitamin_B) → 排第三位
内容的提问来源于stack exchange,提问作者Wilker
相关产品推荐
相关产品推荐

