JavaScript合并两个数组 为订单数据添加orderHasAlcohol字段
问题需求
现有两组数据:订单数组ordersData、拣货单数据pickingOrder,二者通过orderId(对应订单数据里的id字段)关联匹配。拣货单是嵌套结构,内部存储了orderHasAlcohol字段,需要生成新数组,把拣货单中对应订单的orderHasAlcohol字段合并到原订单数据的对应项中。优先支持Ramda函数式实现,原生JS实现也可接受。
原始数据
订单数组 ordersData
const ordersData = [ { additionalInfo: null, comment: null, deliveryDate: "2022-07-14", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "1234", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", }, { additionalInfo: null, comment: null, deliveryDate: "2022-07-23", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "123", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", }, { additionalInfo: null, comment: null, deliveryDate: "2022-07-23", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "198", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", }, { additionalInfo: null, comment: null, deliveryDate: "2022-07-23", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "125", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", }, ];
拣货单数据 pickingOrder
const pickingOrder = { ordersPickedAndDone: { orderCount: 0, rows: [], }, ordersPickedAndPaid: { orderCount: 0, rows: [], }, ordersPickedCanStart: { orderCount: 2, rows: [ { orderHasAlcohol: false, orderId: "123", }, { orderHasAlcohol: true, orderId: "198", }, ], }, ordersPickingProgress: { orderCount: 2, rows: [ { pickingRun: 1, partitions: [ { orderHasAlcohol: false, orderId: "125", }, { orderHasAlcohol: true, orderId: "1234", }, ], }, ], }, };
预期输出
const expectedArrays = [ { additionalInfo: null, comment: null, deliveryDate: "2022-07-14", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "1234", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", orderHasAlcohol: true, }, { additionalInfo: null, comment: null, deliveryDate: "2022-07-23", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "123", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", orderHasAlcohol: false, }, { additionalInfo: null, comment: null, deliveryDate: "2022-07-23", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "198", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", orderHasAlcohol: true, }, { additionalInfo: null, comment: null, deliveryDate: "2022-07-23", deliveryMethod: "PICKUP", deliveryTime: "10-12", discountCode: null, id: "125", // orderId orderStatus: "NEW", paymentMethod: "ON_DELIVERY", paymentStatus: "UNAVAILABLE", storeId: "12345", orderHasAlcohol: false, }, ]; console.log({expectedArrays});
实现方案
核心逻辑分两步:
- 先遍历嵌套的拣货单结构,把所有
orderId和对应的orderHasAlcohol提取成扁平映射表,避免重复遍历深层结构,提升匹配效率 - 遍历原订单数组,从映射表中取出对应字段合并到订单对象中,全程不修改原始数据
方案1:原生JS实现
// 1. 构建orderId -> orderHasAlcohol的映射 const alcoholMap = {}; // 提取普通rows层级的订单 Object.values(pickingOrder).forEach(statusGroup => { statusGroup.rows?.forEach(row => { if (row.orderId) { alcoholMap[row.orderId] = row.orderHasAlcohol; } // 提取partitions嵌套层级的订单 row.partitions?.forEach(partition => { if (partition.orderId) { alcoholMap[partition.orderId] = partition.orderHasAlcohol; } }) }) }) // 2. 合并字段到原订单 const mergedOrders = ordersData.map(order => ({ ...order, orderHasAlcohol: alcoholMap[order.id] }))
方案2:Ramda函数式实现
遵循Ramda无点风格编写,逻辑和原生实现一致,扩展性更强:
import * as R from 'ramda'; // 递归提取单条拣货记录(兼容普通row和多层嵌套结构) const extractOrderEntry = R.cond([ [R.has('orderId'), item => R.objOf(item.orderId, item.orderHasAlcohol)], [R.has('partitions'), R.pipe( R.prop('partitions'), R.map(extractOrderEntry), R.mergeAll )], [R.T, R.always({})] ]) // 构建alcohol映射表 const buildAlcoholMap = R.pipe( R.values, R.map(R.prop('rows')), R.flatten, R.map(extractOrderEntry), R.mergeAll ) // 合并订单 const mergeOrders = R.converge( R.mapWith((order, alcoholMap) => R.assoc('orderHasAlcohol', alcoholMap[order.id], order)), [R.identity, buildAlcoholMap] ) // 调用获取结果 const mergedOrders = mergeOrders(ordersData, pickingOrder)
两种方案输出结果和预期完全一致,如果后续拣货单新增其他嵌套层级,只需要在提取映射的逻辑里补充对应层级的遍历规则即可。
内容的提问来源于stack exchange,提问作者user12494839
相关产品推荐
相关产品推荐

