从数组中删除元素的更好(更快)方法是什么?

4

我正在尝试根据索引数组从一个数组中删除元素。

这是我的代码:

const array = [0, 1, 2, 3, 4, 5];
const indicesToRemove = [0, 2, 5];

for (let i = indicesToRemove.length; i--;) {
    array.splice(indicesToRemove[i], 1);
}

console.log(array);

结果: [1, 3, 4]

看起来它运行良好,但我想知道是否有更好/更快的方式来实现相同的功能。


这个回答解决了你的问题吗?如何从数组中删除特定项? - William Prigol Lopes
@WilliamPrigolLopes 我的问题更多关于性能而不是如何实现。 - Zack Lee
3个回答

3
如果你能将不包含这些元素的数组放入一个的变量名中,我建议使用filter过滤掉在indiciesToRemove中的索引:

const array = [0, 1, 2, 3, 4, 5];
const indicesToRemove = [0, 2, 5];

const filtered = array.filter((_, i) => !indicesToRemove.includes(i));

console.log(filtered);

为了减少计算复杂度,使用Set代替,这样你只需要在一次迭代中遍历indiciesToRemove,而不是每次迭代都要遍历:

const array = [0, 1, 2, 3, 4, 5];
const indicesToRemove = new Set([0, 2, 5]);

const filtered = array.filter((_, i) => !indicesToRemove.has(i));

console.log(filtered);


1
如果这两个数组非常大,使性能成为问题,那么使用Set解决方案肯定会更快——它将总体复杂度从“O(n ^ 2)”降低到“O(n)”。 - CertainPerformance
当我运行基准测试时,似乎我的比你的快一点:https://jsben.ch/EyhFO - Zack Lee
@ZackLee 如果你的数据集很小,性能并不重要,因为操作几乎是瞬间完成的。如果你有大型数据集,无论是.filter还是Set方法都比splice快得多。 - CertainPerformance
@Zack Lee,你的基准代码有误。其中一个每次都在进行搜索,而另一个则只是删除位置而不进行搜索。 - user120242
@CertainPerformance 我已经添加了使用Set的测试,但它仍然比较慢。 - Chris
显示剩余6条评论

1
这个怎么样:
arr = array.filter( function(indicesToRemove) {
  return !toRemove.includes(indicesToRemove);
} );

console.log(arr)

1

拼接是最快的方法

const array = [0, 1, 2, 3, 4, 5];
const indicesToRemove = [0, 2, 5];

for (let index = indicesToRemove.length; index >= 0 ; index--) {
  array.splice(index, 1);
}

如果你处理大量数据并创建新的数组,例如filter或push,你将遇到内存问题。
基准测试:
// setup
const array1 = [...new Array(5000).keys()];
const indicesToRemove1 = [...new Array(5000).keys()];

const array2 = [...new Array(5000).keys()];
const indicesToRemove2 = [...new Array(5000).keys()];

const array3 = [...new Array(5000).keys()];
const indicesToRemove3 = [...new Array(5000).keys()];

const array4 = [...new Array(5000).keys()];
const indicesToRemove4 = new Set([...new Array(5000).keys()]);

测试1

for (let index = indicesToRemove1.length; index >= 0 ; index--) {
    array1.splice(index, 1);
}
// 3,398 ops/s ±0.71%
// fastest

测试2

for (let index = indicesToRemove2.length; index--;) {
    array2.splice(index, 1);
}
// 3,377 ops/s ±0.53%
// 0.62% slower

测试 3

const newArray = array4.filter((_,i) => !indicesToRemove4.has(i))
// 3,322 ops/s ±0.5%
// 2.25% slower

测试4

const newArray = array3.filter((_,i) => !indicesToRemove3.includes(i))
// 22 ops/s ±5.6%
// 99.35% slower

但是在正向循环中删除元素不是很危险吗?这不会影响原始数组的索引吗? - Zack Lee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接