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

NgRx场景下如何快速查找数组中指定属性名的元素并替换

正确实现方案

现有代码问题排查

  • 执行顺序错误:在判断state是否存在前就访问了state.alarms做数组解构,state为空时会直接抛出异常
  • 遍历冗余:find+indexOf的写法会对数组做两次全量遍历,数千条数据规模下高频触发时会有不必要的性能损耗
  • 重复计算:循环判断中每次都执行Object.keys(alarm)[0]获取目标键,可提前提取减少重复计算

基础修复版本

export function addNewAlarm(state: State, alarm: AlarmsObject): State | undefined {
  // 先判断state是否合法
  if (!state) return undefined;
  // 提前提取目标告警键,只计算一次
  const targetKey = Object.keys(alarm)[0];
  // 直接找对应索引,一次遍历完成
  const targetIndex = state.alarms.findIndex(alarmItem => 
    alarmItem.hasOwnProperty(targetKey)
  );
  // 复制原数组
  const newAlarms = [...state.alarms];
  if (targetIndex > -1) {
    // 存在则替换
    newAlarms[targetIndex] = alarm;
  } else {
    // 不存在可按需选择是否追加到数组末尾,不需要可删除该分支
    newAlarms.push(alarm);
  }

  return { ...state, alarms: newAlarms };
}

高性能优化版本(推荐)

由于你无法修改原有数组结构,可以在State中新增一个键到索引的映射表,将查找操作的时间复杂度从O(n)降到O(1),数千条数据场景下性能提升明显:

第一步:修改State定义

export interface State {
  // 原有其他属性
  alarms: AlarmsObject[];
  // 新增映射表:键为告警数字键/global,值为对应在alarms数组中的索引
  alarmKeyIndexMap: Record<string, number>;
}

第二步:修改reducer逻辑

export function addNewAlarm(state: State, alarm: AlarmsObject): State | undefined {
  if (!state) return undefined;
  const targetKey = Object.keys(alarm)[0];
  const newAlarms = [...state.alarms];
  const newMap = {...state.alarmKeyIndexMap};
  const targetIndex = state.alarmKeyIndexMap[targetKey];

  if (targetIndex !== undefined) {
    newAlarms[targetIndex] = alarm;
  } else {
    // 新增元素时同步更新映射表
    const newIndex = newAlarms.length;
    newAlarms.push(alarm);
    newMap[targetKey] = newIndex;
  }

  return { ...state, alarms: newAlarms, alarmKeyIndexMap: newMap };
}

注意:State初始化时需要遍历初始alarms数组,生成初始的alarmKeyIndexMap映射表。

内容的提问来源于stack exchange,提问作者D.Zet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 03:45:02