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

嵌套对象差异对比函数处理数组删除项时结果异常求解

问题根因

你当前的实现将数组视为普通键值对象处理,直接按索引属性进行比对。而数组是有序集合,删除元素后后续元素索引整体前移,原索引对应的元素值发生变化,就会被误判为修改/删除。

修复方案
  • 新增数组类型判断逻辑,数组和普通对象走不同的比对分支
  • 数组比对采用「基于值匹配」的逻辑,而非按索引逐个比对:简单场景可直接先匹配相同位置前的公共元素,再找出后续部分中被删除的元素;如果需要支持元素移动、数组元素为复杂对象的场景,可使用最长公共子序列(LCS)算法做元素匹配
  • 保留原普通对象的比对逻辑,不影响原有功能
修复后代码示例
// 新增数组类型判断辅助方法
static isArray(val) {
  return Object.prototype.toString.call(val) === '[object Array]';
}

static modifiedDiff(o1, o2, deep = false, added = [], updated = [], removed = [], path = "", key = "") {
  path += key.length > 0 ? key + "." : '';

  // 新增数组专属比对分支
  if (this.isArray(o1) && this.isArray(o2)) {
    let i = 0, j = 0;
    const len1 = o1.length, len2 = o2.length;
    // 先匹配前面完全相等的公共元素
    while (i < len1 && j < len2 && o1[i] === o2[j]) {
      // 深对比场景下递归校验数组元素的内部变化
      if (deep && this.isObject(o1[i]) && this.isObject(o2[i])) {
        this.modifiedDiff(o1[i], o2[i], deep, added, updated, removed, path, String(i));
      }
      i++;
      j++;
    }
    // o1剩余的元素为被删除项
    while (i < len1) {
      this.addObjectToArray(removed, path + i, o1[i]);
      i++;
    }
    // o2剩余的元素为新增项(需要支持元素移动的场景可将此处替换为LCS匹配逻辑)
    while (j < len2) {
      this.addObjectToArray(added, path + j, o2[j]);
      j++;
    }
    return {added, updated, removed};
  }

  // 原有普通对象比对逻辑保留,仅优化了冗余判断
  for (const prop in o1) {
    if (o1.hasOwnProperty(prop)) {
      const o2PropValue = o2[prop];
      const o1PropValue = o1[prop];
      if (o2.hasOwnProperty(prop)) {
        if (o2PropValue !== o1PropValue) {
          if (deep && this.isObject(o1PropValue) && this.isObject(o2PropValue)) {
            this.modifiedDiff(o1PropValue, o2PropValue, deep, added, updated, removed, path, this.modifyPropIfNeeded(prop));
          } else {
            this.addObjectToArray(updated, path + prop, o2PropValue);
          }
        }
      } else {
        this.addObjectToArray(removed, path + prop, o1PropValue);
      }
    }
  }
  for (const prop in o2) {
    if (o2.hasOwnProperty(prop) && !o1.hasOwnProperty(prop)) {
      this.addObjectToArray(added, path + prop, o2[prop]);
    }
  }
  return {added, updated, removed};
}
效果验证

用你给出的测试用例modifiedDiff([1,2,3,4], [1,2,4])测试,返回结果完全符合预期:

{
    "added": [],
    "updated": [],
    "removed": [
        {
            "2": 3
        }
    ]
}
扩展说明

如果你的数组元素是复杂对象且可能存在顺序调整、元素重复的场景,可以将数组比对逻辑替换为LCS算法,同时为数组元素增加唯一标识(比如id字段)作为匹配依据,识别准确率会更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 11:36:03