基于updatedItems与起止时段识别可增删改的项及处理逻辑
实现数据项的增删更新识别逻辑
需求概述
通过传入updatedItems,识别出需要执行删除、更新、添加操作的数据项,核心规则如下:
- 若更新项的
start/end与对应现有项不同且无重叠,现有项标记为删除,更新项标记为添加 - 若更新项与现有项
id匹配,且start/end未发生无重叠的变更,仅其他字段(如cost)修改时,标记为更新 - 无匹配
id的更新项直接标记为添加 - 未被任何更新项匹配到的现有项标记为删除
示例数据
现有数据
const existingItems = [ { id: '111', start: 0, end: 10, cost: 100 }, { id: '222', start: 20, end: 30, cost: 200 }, ];
更新数据
const updatedItems = [ { start: 0, end: 9, cost: 42 }, { id: '222', start: 20, end: 30, cost: 999 } ];
预期输出
const items = { deleted: [ { id: '111', start: 0, end: 10, cost: 100 } ], added: [ { start: 0, end: 9, cost: 42 }, ], updated: [ { id: '222', start: 20, end: 30, cost: 999 } ] };
实现代码
function processItems(existingItems, updatedItems) { // 用Map存储带id的现有项,快速查找 const existingMap = new Map(); existingItems.forEach(item => { if (item.id) existingMap.set(item.id, item); }); const deleted = []; const added = []; const updated = []; // 记录更新项中出现的id,用于筛选未被匹配的现有项 const updatedIds = new Set(); // 遍历处理更新项 updatedItems.forEach(updatedItem => { if (updatedItem.id) { updatedIds.add(updatedItem.id); const existingItem = existingMap.get(updatedItem.id); if (existingItem) { // 判断起止区间是否不同且无重叠 const isRangeChangedAndNoOverlap = (updatedItem.start !== existingItem.start || updatedItem.end !== existingItem.end) && !(updatedItem.start < existingItem.end && updatedItem.end > existingItem.start); if (isRangeChangedAndNoOverlap) { deleted.push(existingItem); added.push(updatedItem); } else { updated.push(updatedItem); } } else { added.push(updatedItem); } } else { // 无id的项直接加入添加列表 added.push(updatedItem); } }); // 处理未被匹配的现有项 existingItems.forEach(item => { if (item.id && !updatedIds.has(item.id)) { deleted.push(item); } }); return { deleted, added, updated }; } // 测试示例 const result = processItems(existingItems, updatedItems); console.log(result);
代码说明
- 现有项映射:通过
Map存储带id的现有项,实现O(1)时间复杂度的查找,提升处理效率 - 更新项分类:
- 带
id的项:匹配现有项后,根据起止区间的重叠情况,决定是执行删旧加新还是直接更新 - 无
id的项:直接划入添加列表
- 带
- 剩余项清理:筛选出未被任何更新项匹配的带
id现有项,划入删除列表
内容的提问来源于stack exchange,提问作者cafe123
相关产品推荐
相关产品推荐

