如何使用Lodash判断含嵌套对象的数组并合并累加属性值
嵌套对象数组的订单菜品合并实现
现有实现的问题
之前写的reduce逻辑跑不通的原因很直接:
- 没给reduce传初始值,第一次迭代后reduce的返回值就是单个对象,后续遍历到不匹配项时直接把当前元素返回,会把之前的累计结果全冲掉,根本攒不成最终的合并数组
- 相等判断的逻辑错配:直接拿完整对象喂给
_.isEqual对比,把需要累加的amount字段也纳入了相等判断——毕竟两个同菜品的amount本来就不一样,只要amount不同就会被判为不相等,压根进不去合并分支 - 完全没处理嵌套
mody数组的累加,就算顶层amount算对了,嵌套选项的数值也和预期结构对不上
实现思路
- 调整相等判断规则:对比两个菜品时,忽略所有需要累加的
amount字段(顶层amount、mody内每个子项的amount),只要其他业务维度的字段(id、名称、价格、mody的结构)完全一致,就判定为需要合并的同一项 - 用reduce遍历原始数组,每次取当前菜品去已合并的结果里找匹配项:
- 没找到匹配项:直接把当前菜品加入合并结果
- 找到匹配项:累加顶层amount,同时按mody子项的对应关系累加内部的amount值
完整可运行代码
import _ from 'lodash' // 判断两个菜品是否为需要合并的同一项(忽略amount字段差异) const isSameFood = (foodA, foodB) => { // 剥离所有需要累加的amount字段,仅对比业务维度的相等性 const stripAmount = (obj) => _.omit(obj, 'amount') const normalizedA = { ...stripAmount(foodA), mody: foodA.mody.map(stripAmount) } const normalizedB = { ...stripAmount(foodB), mody: foodB.mody.map(stripAmount) } return _.isEqual(normalizedA, normalizedB) } // 合并同一项的mody数组,累加内部子项的amount const mergeMody = (existMody, newMody) => { // 如果存在mody顺序混乱的情况,可将此处改为按子项id匹配累加,无需依赖数组下标 return existMody.map((item, idx) => ({ ...item, amount: item.amount + newMody[idx].amount })) } // 执行合并 const mergedFood = food.reduce((result, current) => { const matchIndex = result.findIndex(item => isSameFood(item, current)) if (matchIndex < 0) { result.push(current) return result } // 命中匹配项,累加对应数值 const exist = result[matchIndex] result[matchIndex] = { ...exist, amount: exist.amount + current.amount, mody: mergeMody(exist.mody, current.mody) } return result }, [])
注意事项
- 上述代码默认同一项的mody数组顺序完全一致,如果业务场景下存在mody顺序混乱的情况,直接修改
mergeMody的匹配逻辑即可,不需要改动整体流程 - 所有合并操作都是生成新对象,不会修改原始数组的属性,避免污染原始订单数据
内容的提问来源于stack exchange,提问作者brxu
相关产品推荐
相关产品推荐

