基于匹配值重排数组:实现用户搜索结果优先展示
解决方案:基于搜索词的电影数组排序逻辑
以下是完善后的代码实现,完全满足「完整电影名匹配排首位、任意关键词匹配靠前、无匹配项靠后」的排序需求:
const searchTerm = "comedy"; // 可替换为任意搜索词,比如完整电影名"MovNameOne" let movies = [{ "MovNameOne": ["comedy", "fun", "2021"] }, { "MovNameTwo": ["thriller", "suspense", "2022"] }, { "MovNameThree": ["thriller", "comedy", "2021"] }, { "MovNameFour": ["action", "mixed", "2000"] }, { "MovNameFive": ["fun", "mixed", "2021"] }, ]; // 保留原索引,避免同等级匹配项打乱原始顺序 const moviesWithIndex = movies.map((movie, idx) => ({ ...movie, originalIndex: idx })); const sortedMovies = moviesWithIndex.sort((a, b) => { // 提取单个电影的名称和标签数组 const getMovieMeta = (item) => { const name = Object.keys(item)[0]; const tags = Object.values(item)[0]; return { name, tags }; }; const { name: aName, tags: aTags } = getMovieMeta(a); const { name: bName, tags: bTags } = getMovieMeta(b); // 定义匹配优先级:3=完全匹配电影名,2=标签含搜索词,1=无匹配 const getMatchLevel = (name, tags) => { if (name.toLowerCase() === searchTerm.toLowerCase()) return 3; if (tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()))) return 2; return 1; }; const aLevel = getMatchLevel(aName, aTags); const bLevel = getMatchLevel(bName, bTags); // 先按匹配等级降序,等级相同则按原索引升序保持顺序 if (aLevel !== bLevel) return bLevel - aLevel; return a.originalIndex - b.originalIndex; }).map(item => { // 移除临时添加的索引属性,还原原对象格式 const { originalIndex, ...movie } = item; return movie; }); console.log(sortedMovies);
核心逻辑说明
- 原索引保留:通过
map给每个电影对象添加originalIndex,解决JS原生sort不稳定排序导致的同等级项乱序问题。 - 匹配等级划分:
- 最高优先级:电影名称与搜索词完全匹配(不区分大小写),直接锁定首位。
- 次优先级:电影标签数组中包含搜索词(支持部分匹配,不区分大小写),排在完全匹配项之后。
- 最低优先级:无任何匹配的项,排在最后。
- 排序规则:优先按匹配等级降序排列,等级相同时按原索引升序,确保同等级项的原始顺序不变。
- 格式还原:排序完成后移除临时添加的索引属性,保证输出格式与原数组一致。
测试场景示例
- 搜索完整电影名
"MovNameTwo":匹配项会排在首位,其余项按标签匹配情况和原顺序排列。 - 搜索标签关键词
"2021":所有含该标签的电影会集中排在前面,顺序与原数组一致。 - 搜索无匹配词
"drama":数组保持原始顺序不变。
内容的提问来源于stack exchange,提问作者Hunter
相关产品推荐
相关产品推荐

