JavaScript按userId合并订单并累加同bookId的count值
解决订单数据按用户分组并累加书籍数量的问题
你需要将orders数组按userId分组去重,同一用户下相同bookId的count值累加,最终生成包含用户基础信息和对应书籍统计的报表。先说说你现有代码的问题:
- 用
[...new Set(orders)]无法实现对象去重,因为对象是引用类型,Set只会对比内存地址,不会识别内容相同的对象,所以uniqueOrder还是原数组的全部元素。 - 后续的
map+filter逻辑只是给每个订单关联了同用户的所有订单,既没实现用户分组,也没完成书籍数量的累加,最终结果会有大量重复的用户条目。
下面是两种可行的实现方案:
方案一:使用Map构建映射(更安全,支持非数字userId)
const orders = [ {"userId": 1,"name": "Person 1","status": "active","bookId": 24,"count": 1}, {"userId": 1,"name": "Person 1","status": "active","bookId": 25,"count": 2}, {"userId": 2,"name": "Person 2","status": "active","bookId": 8,"count": 2}, {"userId": 1,"name": "Person 1","status": "active","bookId": 24,"count": 3}, {"userId": 3,"name": "Person 3","status": "active","bookId": 99,"count": 1} ]; // 用reduce遍历订单,构建用户分组的Map const userMap = orders.reduce((map, order) => { if (!map.has(order.userId)) { // 初始化用户条目,包含基础信息和存储书籍的Map map.set(order.userId, { userId: order.userId, name: order.name, status: order.status, orders: new Map() }); } const userEntry = map.get(order.userId); if (!userEntry.orders.has(order.bookId)) { // 初始化书籍统计条目 userEntry.orders.set(order.bookId, { bookId: order.bookId, count: 0 }); } // 累加书籍数量 userEntry.orders.get(order.bookId).count += order.count; return map; }, new Map()); // 将Map转换为最终需要的数组格式 const results = Array.from(userMap.values()).map(user => ({ ...user, orders: Array.from(user.orders.values()) })); console.log(results);
方案二:使用普通对象构建映射(更简洁,适合数字userId)
const orders = [ {"userId": 1,"name": "Person 1","status": "active","bookId": 24,"count": 1}, {"userId": 1,"name": "Person 1","status": "active","bookId": 25,"count": 2}, {"userId": 2,"name": "Person 2","status": "active","bookId": 8,"count": 2}, {"userId": 1,"name": "Person 1","status": "active","bookId": 24,"count": 3}, {"userId": 3,"name": "Person 3","status": "active","bookId": 99,"count": 1} ]; const userObj = {}; orders.forEach(order => { const { userId, name, status, bookId, count } = order; // 初始化用户条目 if (!userObj[userId]) { userObj[userId] = { userId, name, status, orders: {} }; } const user = userObj[userId]; // 初始化书籍统计条目 if (!user.orders[bookId]) { user.orders[bookId] = { bookId, count: 0 }; } // 累加数量 user.orders[bookId].count += count; }); // 将对象转换为最终数组格式 const results = Object.values(userObj).map(user => ({ ...user, orders: Object.values(user.orders) })); console.log(results);
两种方案的核心逻辑一致:先按userId完成用户分组,再在每个用户组内按bookId完成数量累加,最后将映射结构转换为你需要的数组格式。
内容的提问来源于stack exchange,提问作者eneooo
相关产品推荐
相关产品推荐

