TypeScript中从ClosureSummary数组提取字段生成无重复MultiselectItem失效
问题原因
当前去重逻辑失效的核心原因是:indexOf 对引用类型做比对时,判断的是对象的内存地址而非内部属性值。map 方法生成的每一个 MultiselectItem 都是独立的新对象,即使两个对象的 id 和 name 完全一致,内存地址也不相同,因此 self.indexOf(elem) 永远会返回当前元素的索引,过滤逻辑不会生效。
正确实现方案
方案1:Set记录已出现ID(推荐,时间复杂度O(n))
用Set存储已经处理过的DomainCode,遍历判断时时间复杂度为常数级,适合大数据量场景:
const existedDomainCodes = new Set<string>(); this.closureDomains = res .map(x => ({ id: x.DomainCode, name: x.Domain })) .filter(item => { if (existedDomainCodes.has(item.id)) return false; existedDomainCodes.add(item.id); return true; });
方案2:Map去重(可读性更高)
利用Map键唯一的特性实现去重,如需保留第一个/最后一个出现的重复项,调整写入逻辑即可:
const domainMap = new Map<string, MultiselectItem>(); res.forEach(x => { // 若要保留第一个出现的同ID项,可加判断 if (!domainMap.has(x.DomainCode)) 再执行set domainMap.set(x.DomainCode, { id: x.DomainCode, name: x.Domain }); }); this.closureDomains = Array.from(domainMap.values());
方案3:改造原有filter逻辑(仅适合小数据量)
如果要沿用原有的链式写法,可以将indexOf替换为按ID匹配的findIndex,缺点是时间复杂度为O(n²),数据量大时性能较差:
this.closureDomains = res .map(x => ({ id: x.DomainCode, name: x.Domain })) .filter((item, index, self) => index === self.findIndex(elem => elem.id === item.id) );
内容的提问来源于stack exchange,提问作者Sandeep Thomas
相关产品推荐
相关产品推荐

