如何根据bstatus优先级去除对象数组中的重复id项
按状态规则去重对象数组实现
去重规则
- 同一id存在多条数据时,优先保留
bstatus:"confirm"的条目,过滤其余同id重复项 - 若同id下无confirm状态条目、仅存在checkout状态条目,则保留
bstatus:"checkout"的条目 - 需过滤排除
bstatus:"reserve"、status:"cancel"的条目
原始测试数组
[ { "id": "1", "room_no": "Room No 101", "status": "confirm", "created_at": "2021-10-27 17:41:05", "bid": "70", "rid": "1", "guest_name": "test", "tariff": "2000", "apaid": "2000", "ckdate": "2022-06-17", "bstatus": "confirm" }, { "id": "1", "room_no": "Room No 101", "status": "confirm", "created_at": "2021-10-27 17:41:05", "bid": "72", "rid": "1", "guest_name": "sad", "tariff": "2222", "apaid": "2222", "ckdate": "2022-07-29", "bstatus": "reserve" }, { "id": "1", "room_no": "Room No 101", "status": "confirm", "created_at": "2021-10-27 17:41:05", "bid": "73", "rid": "1", "guest_name": "abid", "tariff": "2500", "apaid": "2500", "ckdate": "2022-06-15", "bstatus": "checkout" }, { "id": "2", "room_no": "Room No 102", "status": "checkout", "created_at": "2021-10-27 17:41:05", "bid": null, "rid": "2", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "3", "room_no": "Room No 103", "status": "checkout", "created_at": "2021-10-27 17:41:05", "bid": null, "rid": "3", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "4", "room_no": "Room No 104", "status": "checkout", "created_at": "2021-10-27 17:41:05", "bid": null, "rid": "4", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "5", "room_no": "Room No 105", "status": "checkout", "created_at": "2021-10-27 17:41:05", "bid": null, "rid": "5", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "6", "room_no": "Room No 106", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "6", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "7", "room_no": "Room No 201", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "7", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "8", "room_no": "Room No 202", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "8", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "9", "room_no": "Room No 203", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "9", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "10", "room_no": "Room No 204", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "10", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "11", "room_no": "Room No 205", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "11", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "12", "room_no": "Room No 206", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "12", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null } ]
预期输出结果
[ { "id": "1", "room_no": "Room No 101", "status": "confirm", "created_at": "2021-10-27 17:41:05", "bid": "70", "rid": "1", "guest_name": "test", "tariff": "2000", "apaid": "2000", "ckdate": "2022-06-17", "bstatus": "confirm" }, { "id": "2", "room_no": "Room No 102", "status": "checkout", "created_at": "2021-10-27 17:41:05", "bid": null, "rid": "2", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "3", "room_no": "Room No 103", "status": "checkout", "created_at": "2021-10-27 17:41:05", "bid": null, "rid": "3", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "4", "room_no": "Room No 104", "status": "checkout", "created_at": "2021-10-27 17:41:05", "bid": null, "rid": "4", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "5", "room_no": "Room No 105", "status": "checkout", "created_at": "2021-10-27 17:41:05", "bid": null, "rid": "5", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "6", "room_no": "Room No 106", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "6", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "7", "room_no": "Room No 201", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "7", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "8", "room_no": "Room No 202", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "8", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "9", "room_no": "Room No 203", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "9", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "10", "room_no": "Room No 204", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "10", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "11", "room_no": "Room No 205", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "11", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null }, { "id": "12", "room_no": "Room No 206", "status": "checkout", "created_at": "2021-10-27 17:41:06", "bid": null, "rid": "12", "guest_name": null, "tariff": null, "apaid": null, "ckdate": null, "bstatus": null } ]
原有代码问题
原有倒序遍历逻辑只实现了「同id只保留遍历到的第一条非排除项」,没有做状态优先级判断:倒序遍历id=1的条目时,最先碰到的是bstatus:checkout的条目,会被直接存入结果,后续遍历到优先级更高的bstatus:confirm条目时,因为id已经被标记过,会被直接跳过,最终保留的是低优先级数据,不符合要求。
原有实现代码如下:
for (var i = res.data.length - 1; i >= 0; i--) { if (index.indexOf(res.data[i].id) === -1) { if(res.data[i].bstatus !== 'reserve' && res.data[i].status !== 'cancel') { index.push(res.data[i].id); result.unshift(res.data[i]); } } }
正确实现代码
用Map按id存储条目,遍历过程中按优先级判断是否替换已存条目即可,代码如下:
const idMap = new Map(); // 第一步先过滤掉所有明确要排除的条目 const validItems = res.data.filter(item => { return item.bstatus !== 'reserve' && item.status !== 'cancel'; }); validItems.forEach(item => { const stored = idMap.get(item.id); // 同id无已存条目,直接存入 if (!stored) { idMap.set(item.id, item); return; } // 已存条目不是最高优先级confirm,当前条目是confirm,替换为高优先级条目 if (stored.bstatus !== 'confirm' && item.bstatus === 'confirm') { idMap.set(item.id, item); } }); // 转为数组即为最终结果 const result = Array.from(idMap.values());
逻辑说明
- 先过滤无效条目减少后续遍历计算量
- 同id首次出现直接存入Map
- 同id重复出现时,只有当前条目优先级高于已存条目才做替换,保证最终每个id保留的是最高优先级的有效条目
- 运行后输出结果和预期完全一致。
内容的提问来源于stack exchange,提问作者Mohammed
相关产品推荐
相关产品推荐

