TypeScript实现addOrUpdate函数遇阻:对象数组增改需求求助
问题描述
我正在尝试实现一个addOrUpdate函数,但多次尝试都失败了。我有一个对象数组,每个对象包含valueGroup键和values字符串数组(类型定义为SelectedValues)。需求逻辑如下:首先检查对应valueGroup的对象是否存在,不存在则新增;若存在,检查目标value是否在其values数组中,存在则删除,不存在则添加。我最初尝试用函数式方法(map)实现,但出现了嵌套数组的问题,希望完全用函数式方式解决。目前现有代码无法更新对象,总是新增包含新值的对象,而且代码过于复杂。我使用的是TypeScript,以下是我的代码:
type SelectedValues = { valueGroup: string; values: string[]; }; function updateSelectedValues(selectedValues: SelectedValues[], valueGroup: string, value: string): SelectedValues[] { // If array empty add first object if (selectedValues.length === 0) { return [{ valueGroup: valueGroup, values: [value] }]; } else { // look if valueGroup is already there const index = selectedValues.findIndex((find) => find.valueGroup === valueGroup); if (index === -1) { // if no add new valueGroup with first values return [...selectedValues, { valueGroup: valueGroup, values: [value] }]; } else { // if valueGroup is there, look if value is already in values const findedValues = selectedValues[index]; if (findedValues.values.includes(value)) { // yes, remove value from values return [...selectedValues, { ...findedValues, values: findedValues.values.filter((filter) => filter !== value) }]; } else { // no, add value to values return [ ...selectedValues.filter((object) => object.valueGroup === valueGroup), { ...findedValues, values: [...findedValues.valueGroup, value] }, ]; } } } }
我通过按钮点击事件传入valueGroup和value,期望数组按以下示例变化:
// 初始状态:数组为空,逐步插入两个分组并填充值 const initialState: SelectedValues[] = [ { valueGroup: "valueGroupOne", values: ["some", "more", "example"] }, { valueGroup: "valueGroupTwo", values: ["ddd", "sss", "aaa"] } ]; // 新增一个分组后的状态 const afterAddGroup: SelectedValues[] = [ { valueGroup: "valueGroupOne", values: ["some", "more", "example"] }, { valueGroup: "valueGroupTwo", values: ["ddd", "sss", "aaa"] }, { valueGroup: "valueGroupThree", values: ["ssss", "dddsd", "adsdas"] } ]; // 向已有分组添加新值后的状态 const afterAddValue: SelectedValues[] = [ { valueGroup: "valueGroupOne", values: ["some", "more", "example", "newValueadded"] }, { valueGroup: "valueGroupTwo", values: ["ddd", "sss", "aaa"] }, { valueGroup: "valueGroupThree", values: ["ssss", "dddsd", "adsdas"] } ]; // 从已有分组删除值后的状态 const afterRemoveValue: SelectedValues[] = [ { valueGroup: "valueGroupOne", values: ["some", "more", "example"] }, { valueGroup: "valueGroupTwo", values: ["ddd", "sss", "aaa"] }, { valueGroup: "valueGroupThree", values: ["ssss", "dddsd", "adsdas"] } ];
现有代码问题分析
- 更新逻辑错误:处理已存在
valueGroup的删除/添加操作时,错误地将修改后的对象追加到原数组末尾(比如return [...selectedValues, 新对象]),导致原分组对象保留,新增重复对象,而非替换原对象。 - 语法错误:添加值的逻辑中,
[...findedValues.valueGroup, value]误用了valueGroup(字符串类型),展开后会变成字符数组,正确应该是[...findedValues.values, value]。 - 分支冗余:单独处理空数组的分支,增加了代码复杂度;使用
findIndex加索引访问的方式,不如函数式遍历简洁。
函数式解决方案
以下是纯函数式的实现,通过map遍历数组处理更新,统一逻辑分支,避免修改原数据:
type SelectedValues = { valueGroup: string; values: string[]; }; function updateSelectedValues( selectedValues: SelectedValues[], targetGroup: string, targetValue: string ): SelectedValues[] { let groupExists = false; // 遍历数组,处理匹配的分组 const updatedArray = selectedValues.map(item => { if (item.valueGroup !== targetGroup) { return item; } groupExists = true; // 处理values:存在则删除,不存在则添加 const updatedValues = item.values.includes(targetValue) ? item.values.filter(v => v !== targetValue) : [...item.values, targetValue]; return { ...item, values: updatedValues }; }); // 未找到目标分组时,新增分组 return groupExists ? updatedArray : [...updatedArray, { valueGroup: targetGroup, values: [targetValue] }]; }
实现说明
- 纯函数特性:所有操作均返回新的数组和对象,不修改原数据,符合函数式编程要求。
- 逻辑统一:无需单独处理空数组,空数组时
map返回空数组,自动进入新增分支。 - 高效遍历:仅遍历数组一次完成更新判断与处理,性能更优。
- 错误修正:修复了原代码中
valueGroup误用的问题,确保values数组操作正确。
测试示例
对应你期望的场景,调用示例如下:
// 初始状态 let state: SelectedValues[] = []; // 新增第一个分组 state = updateSelectedValues(state, "valueGroupOne", "some"); state = updateSelectedValues(state, "valueGroupOne", "more"); state = updateSelectedValues(state, "valueGroupOne", "example"); // 新增第二个分组 state = updateSelectedValues(state, "valueGroupTwo", "ddd"); state = updateSelectedValues(state, "valueGroupTwo", "sss"); state = updateSelectedValues(state, "valueGroupTwo", "aaa"); // 新增第三个分组 state = updateSelectedValues(state, "valueGroupThree", "ssss"); state = updateSelectedValues(state, "valueGroupThree", "dddsd"); state = updateSelectedValues(state, "valueGroupThree", "adsdas"); // 向第一个分组添加新值 state = updateSelectedValues(state, "valueGroupOne", "newValueadded"); // 从第一个分组删除值 state = updateSelectedValues(state, "valueGroupOne", "newValueadded");
内容的提问来源于stack exchange,提问作者maxfromgermany
相关产品推荐
相关产品推荐

