You need to enable JavaScript to run this app. 如何使用Lodash判断含嵌套对象的数组并合并累加属性值
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Lodash判断含嵌套对象的数组并合并累加属性值

嵌套对象数组的订单菜品合并实现

现有实现的问题

之前写的reduce逻辑跑不通的原因很直接:

  • 没给reduce传初始值,第一次迭代后reduce的返回值就是单个对象,后续遍历到不匹配项时直接把当前元素返回,会把之前的累计结果全冲掉,根本攒不成最终的合并数组
  • 相等判断的逻辑错配:直接拿完整对象喂给_.isEqual对比,把需要累加的amount字段也纳入了相等判断——毕竟两个同菜品的amount本来就不一样,只要amount不同就会被判为不相等,压根进不去合并分支
  • 完全没处理嵌套mody数组的累加,就算顶层amount算对了,嵌套选项的数值也和预期结构对不上

实现思路

  1. 调整相等判断规则:对比两个菜品时,忽略所有需要累加的amount字段(顶层amount、mody内每个子项的amount),只要其他业务维度的字段(id、名称、价格、mody的结构)完全一致,就判定为需要合并的同一项
  2. 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.27 13:24:05