如何以最优方式调整数组排序:将最后修改对象置于对应分组末尾?
问题
我有一个对象数组,每个对象包含布尔类型的included字段。点击HTML按钮时会修改该字段的值,需要对数组做如下排序:
included为true的对象排在数组前部,false的排在后部;- 最后修改的对象,如果被改为
false则放在数组末尾;如果被改为true则放在所有true值对象的最后。
以下是我的实现方案,请问这是不是最优解?有没有更优的实现方式?
现有代码
HTML部分
<mat-icon *ngIf="product.included" (click)="applyAction('exclude', product.id)"> remove </mat-icon> <mat-icon *ngIf="!product.included" (click)="applyAction('include', product.id)"> add </mat-icon>
TypeScript部分
applyAction(action: action, id: number): void { const selectedProduct = this.productTypes.find((i) => i.id === id); if (action === 'exclude') { selectedProduct.included = false; } else { selectedProduct.included = true; } this.productTypes = this.productTypes.filter((i) => i.id !== id); this.productTypes.push(selectedProduct); this.productTypes.sort((a, b) => Number(b.included) - Number(a.included)); }
分析与优化方案
原方案的不足
原方案能实现需求,但存在不必要的性能浪费:
- 多次数组遍历与操作:先后执行
filter创建新数组、push添加元素、sort全量排序,三次遍历数组的操作,当数组元素较多时,性能损耗会更明显; - 排序逻辑冗余:
sort会重新排列所有元素,但实际上我们只需要调整被修改元素的位置,不需要对整个数组做排序。
更高效的实现方式
直接定位被修改元素,根据其新的included值,精准移动到目标位置,避免全量排序和多余的数组创建:
优化后的TypeScript代码
applyAction(action: 'include' | 'exclude', id: number): void { const index = this.productTypes.findIndex(item => item.id === id); if (index === -1) return; const selectedProduct = this.productTypes[index]; selectedProduct.included = action === 'include'; // 先移除当前元素 this.productTypes.splice(index, 1); if (selectedProduct.included) { // 找到最后一个included为true的元素位置,插入到它后方 const lastTrueIndex = this.productTypes.findLastIndex(item => item.included); // 若没有true元素则插入到开头,否则插入到最后一个true元素的下一位 const insertPos = lastTrueIndex === -1 ? 0 : lastTrueIndex + 1; this.productTypes.splice(insertPos, 0, selectedProduct); } else { // 改为false则直接放到数组末尾 this.productTypes.push(selectedProduct); } }
简化后的HTML代码
原HTML存在重复结构,可以用三元表达式简化:
<mat-icon (click)="applyAction(product.included ? 'exclude' : 'include', product.id)"> {{ product.included ? 'remove' : 'add' }} </mat-icon>
优化点说明
- 减少数组操作次数:仅用
splice完成元素的移除与插入,最多两次遍历(查找元素索引、查找最后一个true元素位置),比原方案的三次遍历更高效; - 精准定位目标位置:无需全量排序,只调整被修改元素的位置,逻辑更直接;
- 类型更严谨:将
action的类型限定为'include' | 'exclude',避免无效值传入; - HTML代码简化:消除重复的
mat-icon标签,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者rore_a
相关产品推荐
相关产品推荐

