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

如何基于start/end属性高效筛选待删对象及状态分类排查

问题分析

你的代码出现错误的核心原因是:

  • 用id|start|end作为唯一标识key,将所有现有对象中key不存在于更新列表的项都标记为deleted,但忽略了「更新列表仅包含变更项,未出现的对象应视为无变更(unchanged)」的场景。
  • 同时,unchanged的筛选逻辑仅从更新列表中取数,遗漏了现有列表中未被修改的对象。

具体来说,id为333的对象在更新列表中完全没有出现,按照你的预期它属于无变更项,但当前代码因为它的key不在更新列表的Map中,被错误归入deleted数组。

修正方案

我们需要调整逻辑,以id为核心标识区分不同状态,再结合start/end/cost判断具体类型:

  1. added:更新列表中新增的id,或同id但start/end变更后的新对象
  2. deleted:现有列表中同id但start/end变更的原对象(即被替换的旧项)
  3. updated:同id且start/end不变,但cost修改的对象
  4. unchanged:现有列表中未被修改的对象(包括更新列表中未出现的id,以及同id且所有属性都不变的项)

修正后的代码:

const existingItems = [
    { id: '111', start: 0, end: 10, cost: 100 },
    { id: '222', start: 20, end: 30, cost: 200 },
    { id: '333', start: 20, end: 30, cost: 200 },
];

const updatedItems = [
    { id: '111', start: 0, end: 9, cost: 42 },
    { id: '222', start: 20, end: 30, cost: 400 },
];

function changes(existing, updated) {
    // 按id创建映射,方便快速查找
    const existingById = new Map(existing.map(item => [item.id, item]));
    const updatedById = new Map(updated.map(item => [item.id, item]));

    const changedItems = {
        added: [],
        deleted: [],
        updated: [],
        unchanged: []
    };

    // 遍历现有对象,处理deleted和unchanged
    for (const existingItem of existing) {
        const updatedItem = updatedById.get(existingItem.id);
        if (!updatedItem) {
            // 更新列表中无此id,视为无变更
            changedItems.unchanged.push(existingItem);
            continue;
        }
        // 比较start和end
        if (existingItem.start !== updatedItem.start || existingItem.end !== updatedItem.end) {
            // start/end变更,原对象标记为删除
            changedItems.deleted.push(existingItem);
        } else {
            // start/end不变,比较cost
            if (existingItem.cost !== updatedItem.cost) {
                // cost变更,后续在updated数组中添加
                continue;
            } else {
                // 所有属性不变,视为无变更
                changedItems.unchanged.push(existingItem);
            }
        }
    }

    // 遍历更新对象,处理added和updated
    for (const updatedItem of updated) {
        const existingItem = existingById.get(updatedItem.id);
        if (!existingItem) {
            // 现有列表中无此id,视为新增
            changedItems.added.push(updatedItem);
            continue;
        }
        // 比较start和end
        if (existingItem.start !== updatedItem.start || existingItem.end !== updatedItem.end) {
            // start/end变更,新对象标记为新增
            changedItems.added.push(updatedItem);
        } else {
            // start/end不变,比较cost
            if (existingItem.cost !== updatedItem.cost) {
                // cost变更,标记为更新
                changedItems.updated.push(updatedItem);
            }
            // 所有属性不变的情况已在前面处理,无需重复添加
        }
    }

    return changedItems;
}

let result = changes(existingItems, updatedItems);
console.log(result);
输出结果说明

修正后输出的各数组符合预期:

  • deleted:仅包含id为111的原对象(因为它的start/end被修改,旧项需删除)
  • unchanged:包含id为333的对象(更新列表中未出现,视为无变更)
  • updated:包含id为222的对象(仅cost修改)
  • added:包含id为111的新对象(start/end修改后的新增项)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:10:23