You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 02:15:04