Angular中基于restaurantId和turnName过滤对象数组问题求助
嘿,我来帮你排查这个问题!
问题出在哪?
你当前的双重forEach循环逻辑有个明显的问题:每一个restaurantSelectedTurns里的条目,都会和arrayOfBookings里的每一条同restaurantId的记录做对比。举个例子,12:00_am这个时段会和arrayOfBookings里的两个restaurantId=1的条目分别对比,两次都满足“turnName不同”的条件,所以会被重复push两次到noRepeated数组里——这就是你看到输出有重复项的根源。
修正方案
我们可以换个思路:先把已预订的时段整理成一个高效查找的集合(Set),再遍历目标数组筛选符合条件的项,这样既能避免重复,又能提升性能。
针对单一餐厅(比如restaurantId=1)的场景
this.noRepeated = []; // 第一步:提取restaurantId=1的所有已预订时段,存进Set const bookedTurnsSet = new Set( arrayOfBookings .filter(booking => booking.restaurantId === 1) .map(booking => booking.turnName) ); // 第二步:筛选出restaurantSelectedTurns中符合条件的项 this.noRepeated = restaurantSelectedTurns.filter(turn => { return turn.restaurantId === 1 && !bookedTurnsSet.has(turn.turnName); }); console.log(this.noRepeated); // 输出预期的[{restaurantId:1, turnName:"12:00_am"}, {restaurantId:1, turnName:"01:00_pm"}]
支持所有餐厅的通用场景
如果你的需求是处理所有restaurantId的情况,而不只是特定的某一个,可以先按餐厅ID分组存储已预订时段:
this.noRepeated = []; // 第一步:按restaurantId分组,存储每个餐厅的已预订时段集合 const bookedTurnsByRestaurant: { [key: number]: Set<string> } = {}; arrayOfBookings.forEach(booking => { if (!bookedTurnsByRestaurant[booking.restaurantId]) { bookedTurnsByRestaurant[booking.restaurantId] = new Set(); } bookedTurnsByRestaurant[booking.restaurantId].add(booking.turnName); }); // 第二步:遍历筛选目标数组 this.noRepeated = restaurantSelectedTurns.filter(turn => { const restaurantBookedTurns = bookedTurnsByRestaurant[turn.restaurantId]; // 如果该餐厅没有已预订记录,或者当前时段不在已预订列表中,就保留 return !restaurantBookedTurns || !restaurantBookedTurns.has(turn.turnName); }); console.log(this.noRepeated);
为什么这个方案更好?
- 避免重复添加:Set的唯一性保证了我们只做一次判断,不会因为多重循环导致重复推入数组。
- 性能更优:Set的查找操作是O(1)时间复杂度,比原来的双重循环(O(n*m))效率高得多,数据量大的时候差异会很明显。
- 逻辑更清晰:用
filter和Set的组合,代码可读性更强,后续维护也更方便。
内容的提问来源于stack exchange,提问作者Enrique GF
相关产品推荐
相关产品推荐

