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) });
场景校验
以上实现完全覆盖所有预期场景:
- 编辑+新增标签场景:正确识别被修改的原标签进入删除列表、修改后的新标签和新增标签进入新增列表,最终列表符合预期
- 仅新增标签场景:正确识别新增标签进入新增列表,无删除项
- 删除单个标签场景:正确识别被删除的原标签进入删除列表,无新增项
- 清空所有标签场景:正确识别所有原有标签进入删除列表,无新增项,最终列表为空
原有代码问题说明
- 多余的空数组判断分支是因为初始待删除逻辑只覆盖了「同key但value不同」的编辑场景,漏掉了「key在修改后列表不存在」的纯删除场景,统一匹配规则后不需要额外分支
- 计算保留标签再拼接最终列表属于冗余逻辑,修改后的标签列表本身就是最终要提交的完整结果,不需要重复计算
- 多组重复的标签相等判断没有抽离,后续如果修改匹配规则需要改多处,维护成本高
内容的提问来源于stack exchange,提问作者Pradip
相关产品推荐
相关产品推荐

