TypeScript中如何批量条件更新对象数组的对象键值
问题
我有一个类型为clothesTypes[]、名为objectArray的对象数组,初始定义如下:
const objectArray: clothesTypes[] = [ { trousers: 90, 'skirts and jackets': 47, scarfs: 100, }, ]
另外还有一个类型为userData[]的数组userArray,会在用户购买衣物时动态更新,示例数据如下:
const userArray: userData[] = [ { name: 'David', clothType: 'trousers', price: 45, }, { name: 'Joanna', clothType: 'scarfs', price: 5, }, { name: 'Gillian', clothType: 'trousers', price: 35, }, ]
需求是统计userArray中各clothType对应的对象数量,用统计结果更新objectArray内对象的对应键值。以上述示例数据为例,更新后trousers对应值应为2,'skirts and jackets'对应值应为0,scarfs对应值应为1。
当前实现
我现在写的方法需要手动给每个键单独赋值:
objectArray.map(item => ({ ...item, ...{ trousers: userArray.filter(d => d.clothType === 'trousers').length, 'skirts and jackets': userArray.filter(d => d.clothType === 'skirts and jackets').length, scarfs: userArray.filter(d => d.clothType === 'scarfs').length, }, })),
想知道怎么不用逐个写键名,一次性完成更新?
解答
不需要硬编码每个衣物类型的键,两步就能实现通用更新逻辑,还能避免多次遍历数组的性能损耗:
- 先遍历一次
userArray,用reduce生成「衣物类型-购买次数」的计数映射表 - 遍历
objectArray时,自动读取原对象的所有键,从计数映射表中取对应值替换,没有匹配到购买记录的类型默认赋值0即可
完整实现代码:
// 统计各衣物类型的购买次数 const typeCount = userArray.reduce<Record<string, number>>((count, record) => { const clothType = record.clothType; count[clothType] = (count[clothType] ?? 0) + 1; return count; }, {}); // 通用更新逻辑,不需要手动写任何键名 const updatedObjectArray = objectArray.map(item => { return Object.fromEntries( Object.keys(item).map(key => [key, typeCount[key] ?? 0]) ) as clothesTypes; });
用给出的示例数据运行,最终得到的数组元素为{ trousers: 2, 'skirts and jackets': 0, scarfs: 1 },完全符合预期。
如果你的运行环境不支持Object.fromEntries(比如低版本Node、较老的浏览器),可以用更兼容的遍历写法:
const updatedObjectArray = objectArray.map(item => { const newItem = { ...item }; for (const key in newItem) { newItem[key] = typeCount[key] ?? 0; } return newItem; });
这个写法的优势很明显:
- 后续
clothesTypes新增、删除类型字段时,不需要修改这段更新逻辑,会自动适配 - 只遍历一次
userArray做计数,比原来每个键都调用一次filter遍历全数组的性能好很多,数据量大的时候差异会很明显 - 只要
clothesTypes的类型定义正确,TS不会报类型错误
内容的提问来源于stack exchange,提问作者Rita Rangers
相关产品推荐
相关产品推荐

