Angular中Set类型存储重复值问题:如何实现仅存储唯一值
问题原因
JavaScript/TypeScript 中的Set类型使用SameValueZero算法判断值是否相等,对于Coordinate这种引用类型,判断依据是对象的内存引用地址而非内部属性值。哪怕两个Coordinate对象的latitude、longitude、label属性完全一致,只要是不同的实例,Set.has()都会判定为不相等,因此会出现重复插入的情况。
解决方案
方案1:用唯一标识做去重校验(推荐,性能最优)
不需要修改现有Set结构,额外新增一个存储唯一标识的Set做去重判断,根据业务规则生成唯一键即可:
// 新增辅助方法生成坐标唯一键 private getCoordUniqueKey(coord: Coordinate): string { // 若仅经纬度相同就算重复,用该行即可: // return `${coord.latitude},${coord.longitude}` // 若需要三个属性完全相同才算重复,用该行: return `${coord.latitude},${coord.longitude},${coord.label}` } // 新增存储唯一键的Set private coordUniqueKeys = new Set<string>(); addMarker(coordinate: Coordinate): void { const coordKey = this.getCoordUniqueKey(coordinate); if (!this.coordUniqueKeys.has(coordKey)) { this.coordUniqueKeys.add(coordKey); this.coords.add(coordinate); L.marker([coordinate.latitude, coordinate.longitude], this.icon) .bindPopup('<b>Found location</b><br>' + coordinate.label) .addTo(this.citiesLayerGroup); } }
方案2:自定义坐标Set类,重写相等判断逻辑
如果不想新增辅助变量,可以继承原生Set重写has方法,实现按属性判断重复:
class CoordinateSet extends Set<Coordinate> { override has(target: Coordinate): boolean { for (const item of this) { if ( item.latitude === target.latitude && item.longitude === target.longitude && item.label === target.label ) return true; } return false; } }
修改初始化coords的逻辑即可,其余代码完全不用改:
ngOnInit(): void { // 替换原来的new Set<Coordinate>() this.coords = new CoordinateSet(); this.coordinatesService.coordinates.subscribe((coordinates: Coordinate[]) => { coordinates.forEach((coordinate) => { this.addMarker(coordinate); }); }); }
注意事项
如果坐标数据量超过万级,方案2的遍历判断会有轻微性能损耗,优先选用方案1即可。
内容的提问来源于stack exchange,提问作者Patman
相关产品推荐
相关产品推荐

