代码优化请求:移除数组重复元素并保留最高版本项
数组去重并保留最高版本项的代码优化建议
接口定义
export interface SomeClass { version: number, typeDescription: string }
测试数据
const sthClass: SomeClass[] = [ { typeDescription: "typeA", version: 10 }, { typeDescription: "typeA", version: 21 }, { typeDescription: "typeB", version: 101 }, { typeDescription: "typeC", version: 199 }, { typeDescription: "typeA", version: 220 }, { typeDescription: "typeB", version: 33 }, { typeDescription: "typeA", version: 15}, ];
原代码存在的问题
你的实现可以达成需求,但有几个可优化的点:
- 时间效率偏低:外层循环嵌套
filter遍历,整体时间复杂度为O(n²),数据量较大时性能会明显下降 - 原数组频繁修改:每次通过
splice修改原数组,会触发数组元素移位,额外消耗性能 - 引用依赖风险:
findIndex使用===比较对象引用,若数组元素为克隆/新创建的对象,会无法匹配到正确索引
优化方案
方案一:使用Map分组(最优性能)
通过Map按typeDescription分组,一次遍历即可完成最高版本项的筛选,时间复杂度O(n):
const uniqueMap = new Map<string, SomeClass>(); for (const item of sthClass) { const existingItem = uniqueMap.get(item.typeDescription); // 若当前类型未记录,或当前项版本更高,则更新记录 if (!existingItem || item.version > existingItem.version) { uniqueMap.set(item.typeDescription, item); } } // 将Map的值转为数组,得到最终结果 const filteredArray = Array.from(uniqueMap.values());
优势:
- 仅遍历数组一次,性能最优
- 不修改原数组,返回新数组,符合纯函数设计原则
- 逻辑清晰,避免重复遍历和数组修改操作
方案二:修改原数组(保持引用)
如果需要保留原数组的引用,可在处理完成后替换原数组内容:
const uniqueMap = new Map<string, SomeClass>(); for (const item of sthClass) { const existingItem = uniqueMap.get(item.typeDescription); if (!existingItem || item.version > existingItem.version) { uniqueMap.set(item.typeDescription, item); } } // 清空原数组并插入筛选后的结果,保持原引用不变 sthClass.length = 0; sthClass.push(...Array.from(uniqueMap.values()));
方案三:使用reduce简化代码(适合小型数组)
如果数组规模较小,也可以用Array.reduce写出更简洁的代码:
const filteredArray = sthClass.reduce((acc, current) => { const targetItem = acc.find(item => item.typeDescription === current.typeDescription); if (!targetItem) { acc.push(current); } else if (current.version > targetItem.version) { // 替换为更高版本的项 acc[acc.indexOf(targetItem)] = current; } return acc; }, [] as SomeClass[]);
注意:这个方案的时间复杂度仍为O(n²),适合数据量不大的场景。
内容的提问来源于stack exchange,提问作者Vivek Shukla
相关产品推荐
相关产品推荐

