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
相关产品推荐
相关产品推荐

