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

为什么用Set实现的数组差异检测对fetch返回的对象数组失效?

问题原因

问题本质是Set的等值判断逻辑导致的:

  • Set.prototype.has()方法使用严格相等(===) 做匹配判断
  • 字符串、数字等基础类型按值匹配,只要值相同就会判定为相等
  • 对象类型按内存引用地址匹配,哪怕两个对象的所有属性值完全一致,只要是不同的引用(两次fetch返回的对象就是完全独立的引用),就会判定为不相等
    因此代码中所有元素都会命中else分支被添加到Set中,最终呈现两个数组拼接的效果。
修复方案

需要将对象转换为可按值匹配的基础类型作为判断相等的依据,常用方案有两种:

方案1:基于唯一主键匹配(推荐,性能更高)

如果数组元素存在唯一标识字段(比如id、uuid),用该字段作为匹配依据:

let differenceDetector = (dataA, dataB) => {
  // 存储已出现的主键
  const idSet = new Set();
  // 存储最终差异对象
  const diffList = [];

  // 遍历A数组,记录所有主键
  for (const item of dataA) {
    idSet.add(item.id);
    diffList.push(item);
  }

  // 遍历B数组,对比主键
  for (const item of dataB) {
    if (idSet.has(item.id)) {
      // 主键重复,从差异列表移除
      diffList.splice(diffList.findIndex(i => i.id === item.id), 1);
      idSet.delete(item.id);
    } else {
      // 主键不存在,加入差异列表
      diffList.push(item);
      idSet.add(item.id);
    }
  }

  return diffList;
};

方案2:基于对象序列化匹配(无唯一主键时使用)

如果没有明确的唯一主键,可以把对象序列化后作为匹配依据,注意要保证对象属性顺序一致避免序列化结果不同:

let differenceDetector = (dataA, dataB) => {
  const compareMap = new Map();
  
  // 遍历A数组,序列化后作为key存储
  for (const item of dataA) {
    const key = JSON.stringify(item);
    compareMap.set(key, item);
  }

  // 遍历B数组对比
  for (const item of dataB) {
    const key = JSON.stringify(item);
    if (compareMap.has(key)) {
      compareMap.delete(key);
    } else {
      compareMap.set(key, item);
    }
  }

  return Array.from(compareMap.values());
};

内容的提问来源于stack exchange,提问作者user16856118

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 07:39:03