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

JavaScript计算对象数组差集交集 实现标签增删改接口适配

标签差异计算实现方案

业务背景

UI弹窗打开时会加载已有的键值对格式标签列表,用户可在弹窗内执行新增、删除、编辑标签操作。由于提交修改的API不支持直接编辑标签,需要将编辑操作拆分为「删除被修改的原条目+新增修改后条目」两个步骤,最终需要计算得到待删除标签列表、待新增标签列表、修改后的完整标签列表。

实现逻辑

原有代码逻辑冗余的核心原因是对差异判断做了多余分支拆分,实际上差异规则非常统一,不需要特殊判断:

  • 待删除标签:所有原有标签中,与修改后标签列表任意项都不完成匹配(key、value均相等)的条目,覆盖「用户主动删除」「标签被编辑修改」两种场景
  • 待新增标签:所有修改后标签中,与原有标签列表任意项都不完成匹配的条目,覆盖「用户主动新增」「标签被编辑修改后的新内容」两种场景
  • 最终生效标签列表:就是用户修改完成后的完整标签列表,不需要额外通过保留项+新增项拼接

代码实现

原生JS版本

无第三方依赖,逻辑清晰易维护:

const getTagDiff = (existingTags, modifiedTags) => {
  // 标签相等判断规则:key、value完全一致
  const isSameTag = (tag1, tag2) => tag1.key === tag2.key && tag1.value === tag2.value;

  return {
    tagsToBeDeleted: existingTags.filter(oldTag => !modifiedTags.some(newTag => isSameTag(oldTag, newTag))),
    tagsToBeAdded: modifiedTags.filter(newTag => !existingTags.some(oldTag => isSameTag(oldTag, newTag))),
    finalTagsList: [...modifiedTags]
  }
};

Lodash 简化版本

如果项目已引入Lodash,可以直接用集合方法实现,后续如果标签新增字段,深比较逻辑无需修改:

import _ from 'lodash';

const getTagDiff = (existingTags, modifiedTags) => ({
  tagsToBeDeleted: _.differenceWith(existingTags, modifiedTags, _.isEqual),
  tagsToBeAdded: _.differenceWith(modifiedTags, existingTags, _.isEqual),
  finalTagsList: _.cloneDeep(modifiedTags)
});

场景校验

以上实现完全覆盖所有预期场景:

  • 编辑+新增标签场景:正确识别被修改的原标签进入删除列表、修改后的新标签和新增标签进入新增列表,最终列表符合预期
  • 仅新增标签场景:正确识别新增标签进入新增列表,无删除项
  • 删除单个标签场景:正确识别被删除的原标签进入删除列表,无新增项
  • 清空所有标签场景:正确识别所有原有标签进入删除列表,无新增项,最终列表为空

原有代码问题说明

  1. 多余的空数组判断分支是因为初始待删除逻辑只覆盖了「同key但value不同」的编辑场景,漏掉了「key在修改后列表不存在」的纯删除场景,统一匹配规则后不需要额外分支
  2. 计算保留标签再拼接最终列表属于冗余逻辑,修改后的标签列表本身就是最终要提交的完整结果,不需要重复计算
  3. 多组重复的标签相等判断没有抽离,后续如果修改匹配规则需要改多处,维护成本高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:18:26