如何对包含宝可梦信息的JS对象数组去重并按出现频率排序
问题核心原因
- 原
byCount方法直接将对象作为普通对象的key时,对象会被自动转为[object Object]字符串,所有对象的key完全相同,无法统计不同宝可梦的实际频次 - 分开对名称、图片数组做排序时,同频次的项没有统一排序规则,会出现随机排列的情况,导致两个数组的对应关系错位
实现方案
直接操作你初始获取到的pokemon对象数组,通过「名称+图片地址」的组合作为唯一标识绑定每个宝可梦的两个属性,统计频次后统一排序,从根源避免错位问题。
推荐实现(不污染原型)
function dedupeAndSortPokemon(pokemonList) { const countMap = new Map(); // 统计每个宝可梦的出现频次 for (const pokemon of pokemonList) { if (!pokemon) continue; // 生成唯一key,绑定名称和图片 const uniqueKey = `${pokemon.name}|${pokemon.image}`; if (countMap.has(uniqueKey)) { countMap.get(uniqueKey).count += 1; } else { countMap.set(uniqueKey, { data: pokemon, count: 1 }); } } // 排序后返回去重的对象数组 return Array.from(countMap.values()) .sort((a, b) => { // 优先按频次降序排序 if (b.count !== a.count) { return b.count - a.count; } // 频次相同时按名称排序,保证排序结果稳定不随机 return a.data.name.localeCompare(b.data.name, 'zh-CN'); }) .map(item => item.data); }
使用方式
直接把你爬取得到的pokemon数组传入即可:
const sortedUniquePokemon = dedupeAndSortPokemon(pokemon);
兼容原型扩展的写法
如果需要保留你原来扩展Array原型的使用习惯,可以改写成兼容对象数组的版本:
Array.prototype.byCount = function () { const countMap = new Map(); for (const item of this) { if (!item) continue; // 自动适配对象/字符串类型的数组项 const uniqueKey = typeof item === 'object' ? `${item.name}|${item.image}` : String(item); if (countMap.has(uniqueKey)) { countMap.get(uniqueKey).count += 1; } else { countMap.set(uniqueKey, { data: item, count: 1 }); } } return Array.from(countMap.values()) .sort((a, b) => { if (b.count !== a.count) return b.count - a.count; const sortKeyA = typeof a.data === 'object' ? a.data.name : String(a.data); const sortKeyB = typeof b.data === 'object' ? b.data.name : String(b.data); return sortKeyA.localeCompare(sortKeyB, 'zh-CN'); }) .map(item => item.data); };
直接调用pokemon.byCount()即可得到排序去重后的结果,同时也兼容原来的字符串数组排序场景。
内容的提问来源于stack exchange,提问作者Liiaam93
相关产品推荐
相关产品推荐

