如何使用Lodash更新包含修改与删除项的数组?
使用Lodash更新包含更新与删除项的工时数组的最佳方法
这是个很常见的数组维护场景,用Lodash的话可以很优雅地完成操作,我给你整理了一套清晰高效的实现方案:
首先明确我们的初始数据和响应数据(我补全了deletedHours里的完整id,原问题里的截断应该是笔误):
初始工时数组:
const workedHours = [ {hours: 3, id: 1234, name: 'John Doe'}, {hours: 2, id: 5678, name: 'Steve Harris'}, {hours: 4, id: 1928, name: 'Richard McNeil'}, {hours: 1, id: 9876, name: 'Kirk Hammet'}, {hours: 3, id: 5432, name: 'Lucas Moore'}, ];
收到的更新/删除响应:
const response = { updatedHours: [ {hours: 4, id: 5678, name: 'Steve Harris'}, {hours: 2, id: 9876, name: 'Kirk Hammet'}, ], deletedHours: [ {hours: 3, id: 5432} ] };
分步实现思路
我们可以分两步完成:先删除不需要的项,再更新剩下的条目,逻辑清晰且容易维护:
- 过滤已删除的条目
首先提取所有要删除的id,再用_.reject把这些id对应的项从原数组中移除:
// 提取所有待删除的id集合 const deletedIds = _.map(response.deletedHours, 'id'); // 过滤掉已删除的项,得到未被删除的数组 const filteredHours = _.reject(workedHours, item => _.includes(deletedIds, item.id));
- 更新剩余的条目
遍历过滤后的数组,找到每个条目对应的更新记录(如果有的话),用_.assign合并更新属性,注意这里我们创建新对象,避免修改原数据:
const updatedWorkedHours = _.map(filteredHours, item => { // 在更新列表里找当前项的更新记录 const updateRecord = _.find(response.updatedHours, { id: item.id }); // 有更新就合并,没有就保留原项 return updateRecord ? _.assign({}, item, updateRecord) : item; });
简化的链式写法
如果喜欢更紧凑的代码,可以用Lodash的链式调用把两步合并:
const deletedIds = _.map(response.deletedHours, 'id'); const updatedWorkedHours = _.chain(workedHours) .reject(item => _.includes(deletedIds, item.id)) .map(item => _.assign({}, item, _.find(response.updatedHours, { id: item.id }))) .value();
大数据量场景的优化
如果你的数组规模很大,上面的_.find每次查找都是O(n)的时间复杂度,可以先把updatedHours转成以id为键的对象,把查找效率降到O(1):
const deletedIds = _.map(response.deletedHours, 'id'); // 把更新列表转成id为key的映射对象 const updateMap = _.keyBy(response.updatedHours, 'id'); const updatedWorkedHours = _.chain(workedHours) .reject(item => _.includes(deletedIds, item.id)) .map(item => _.assign({}, item, updateMap[item.id])) .value();
方案优势
- 逻辑清晰:分删除、更新两步,代码可读性强,后续维护起来很方便
- 不可变性:通过创建新对象而非修改原数据,避免了意外的副作用,符合现代前端开发的最佳实践
- 效率可控:基础版本适合小规模数据,优化版本能应对大数据量场景
内容的提问来源于stack exchange,提问作者Leonardo Uribe
相关产品推荐
相关产品推荐

