如何按brandId和productId分组IOrderData生成IOrderTypeData数组
按brandId和productId分组IOrderData生成IOrderTypeData数组(解决无限循环问题)
需求说明
需要将IOrderData格式的数据按brandId和productId(注意productIds数组始终仅包含一个ID)分组,生成IOrderTypeData类型的对象数组。每个分组对应唯一的品牌ID+产品ID组合,组内的差异仅体现在deliveryType字段。
之前尝试用reduce结合循环实现时,出现了浏览器无限循环的问题。
相关类型与测试数据
interface IOrderData { brandId: number productIds: number[] // 接口返回数组,但始终仅含一个ID deliveryType: string // 可选值:air, ground, ship, train moreData: string moreMoreData: string } interface IProduct { productId: number desc: string } interface IOrderTypeData { brandId: number product: IProduct deliveryTypes: IOrderData[] } const products = [ { productId: 100, desc: "some desc" }, { productId: 200, desc: "some desc" } ] const orderData = [ { brandId: 1, productIds: [100], deliveryType: "Ground", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 1, productIds: [100], deliveryType: "Air", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 1, productIds: [200], deliveryType: "Ground", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 1, productIds: [200], deliveryType: "Air", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 2, productIds: [100], deliveryType: "Ground", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 2, productIds: [100], deliveryType: "Air", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 2, productIds: [200], deliveryType: "Ground", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 2, productIds: [200], deliveryType: "Air", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" } ];
解决方案
之前出现无限循环大概率是因为在查找对应产品时错误使用了未正确终止的循环,或是在reduce中意外修改原数组导致重复处理。以下是高效且避免循环问题的实现:
// 预先生成产品ID到产品对象的映射,避免重复遍历products数组 const productMap = new Map<number, IProduct>( products.map(p => [p.productId, p]) ); // 使用reduce分组,生成临时对象存储分组结果 const groupedObj = orderData.reduce<Record<string, IOrderTypeData>>((acc, order) => { const productId = order.productIds[0]; // 生成唯一分组键:品牌ID+产品ID组合 const groupKey = `${order.brandId}-${productId}`; if (!acc[groupKey]) { // 分组不存在时,创建新的IOrderTypeData对象 acc[groupKey] = { brandId: order.brandId, product: productMap.get(productId)!, // 确保productId存在于products中 deliveryTypes: [] }; } // 将当前订单添加到对应分组的deliveryTypes数组 acc[groupKey].deliveryTypes.push(order); return acc; }, {}); // 将分组对象转换为数组,得到最终结果 const groupedData = Object.values(groupedObj);
结果验证
执行上述代码后,groupedData将完全符合期望的结构:
const groupedData = [ { brandId: 1, product: { productId: 100, desc: "some desc" }, deliveryTypes: [ { brandId: 1, productIds: [100], deliveryType: "Ground", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 1, productIds: [100], deliveryType: "Air", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" } ] }, { brandId: 1, product: { productId: 200, desc: "some desc" }, deliveryTypes: [ { brandId: 1, productIds: [200], deliveryType: "Ground", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 1, productIds: [200], deliveryType: "Air", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" } ] }, { brandId: 2, product: { productId: 100, desc: "some desc" }, deliveryTypes: [ { brandId: 2, productIds: [100], deliveryType: "Ground", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 2, productIds: [100], deliveryType: "Air", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" } ] }, { brandId: 2, product: { productId: 200, desc: "some desc" }, deliveryTypes: [ { brandId: 2, productIds: [200], deliveryType: "Ground", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" }, { brandId: 2, productIds: [200], deliveryType: "Air", moreData: "Some Preserved Data", moreMoreData: "Some Preserved Data" } ] } ]
关键优化点
- 预生成产品映射:用
Map存储产品ID与对象的对应关系,O(1)时间查找产品,避免反复遍历products数组可能引发的循环错误。 - 唯一分组键:用
brandId-productId作为分组标识,确保每个组合唯一。 - 纯函数式reduce处理:
reduce过程中仅操作累加器对象,不修改原orderData数组,避免因数组变更导致的重复处理问题。
内容的提问来源于stack exchange,提问作者WebDevz
相关产品推荐
相关产品推荐

