如何在 JavaScript 中迭代数组并删除元素 [重复]

Posted

技术标签:

【中文标题】如何在 JavaScript 中迭代数组并删除元素 [重复]【英文标题】:How to iterate over an array and remove elements in JavaScript [duplicate] 【发布时间】:2013-04-27 11:33:12 【问题描述】:

我有一个元素数组,需要从中删除某些元素。问题是 javascript 似乎没有 for each 循环,如果我使用 for 循环,我会遇到问题,它基本上试图检查数组边界之外的元素,或者由于索引更改而丢失数组中的元素.让我告诉你我的意思:

var elements = [1, 5, 5, 3, 5, 2, 4];
for(var i = 0; i < elements.length; i++)
    if(elements[i] == 5)
        elements.splice(i, 1);
    

问题是当元素[1]被移除时,元素[2]变成了元素[1]。所以第一个问题是某些元素从未被检查过。另一个问题是 .length 发生了变化,如果我对边界进行硬编码,那么我可能会尝试检查超出数组边界的元素。那么,完成这个极其简单的事情的最佳方法是什么?

【问题讨论】:

elements.splice(i--, 1); 我不喜欢 "--" 或 "++" 语法,但是从数组 +1 的开头开始时很有用的提示 另见:Looping through array and removing items, without breaking for loop 【参考方案1】:

var elements = [1, 5, 5, 3, 5, 2, 4];    
var i = elements.length;
while (i--) 
    if (elements[i] == 5) 
        elements.splice(i, 1);
    

console.log(elements);

【讨论】:

就代码可读性而言,这个答案很可爱【参考方案2】:

您可以在删除项目时简单地减少 i

var elements = [1, 5, 5, 3, 5, 2, 4];

var l = elements.length;
for(var i = 0; i < l; i++)
    if(elements[i] == 5)
        elements.splice(i, 1);
        i--;
    


console.log(elements);

【讨论】:

【参考方案3】:

使用Array.shift():

var array = [1, 2, 3, 'a', 'b', 'c'];
while (array.length > 0) 
  console.log(array.shift());

编辑:可能不符合规格。我误读了这个问题(仅删除 某些 元素)并且太急于添加尚未提及的方法...

【讨论】:

正如您在编辑中所说,这实际上并不能回答问题,但它确实回答了我试图搜索的问题。谢谢。【参考方案4】:

您可以在这里使用filter 方法:

var elements = [1, 5, 5, 3, 5, 2, 4].filter(function(a)return a !== 5;);
//=> elements now [1,3,2,4]

或者如果你不想碰elements

var elementsfiltered
   ,elements = [1, 5, 5, 3, 5, 2, 4]
                .filter( function(a)if (a!==5) this.push(a); return true;,
                         elementsfiltered = [] );
   //=> elementsfiltered = [1,3,2,4], elements = [1, 5, 5, 3, 5, 2, 4]

filterMDN documentation

您也可以扩展Array.prototype

Array.prototype.remove = Array.prototype.remove || function(val)
    var i = this.length;
    while(i--)
        if (this[i] === val)
            this.splice(i,1);
        
    
;
var elements = [1, 5, 5, 3, 5, 2, 4];
elements.remove(5);
//=> elements now [1,3,2,4]

【讨论】:

虽然创建一个新数组,过滤器确实是一个不错的解决方案,但 OP 实际上确实询问了关于删除内联元素的问题,最好举个例子。跨度> 似乎不必要地偏离了原始代码。 OP 可以通过在拼接后减少 i 来保留他现有的代码。 我个人觉得过滤器更安全,因为递减我可能会导致边缘情况,就好像零元素存在等【参考方案5】:

这是使用Array.indexOf、while 和Array.splice 删除内联元素的示例。

var elements = [1, 5, 5, 3, 5, 2, 4];
var remove = 5;
var index = elements.indexOf(remove);

while (index !== -1) 
    elements.splice(index, 1);
    index = elements.indexOf(remove);


console.log(elements);

开启jsfiddle

【讨论】:

低效 O(n^2) 算法被否决 我从来没有对效率提出任何要求,问题并不关心这一点,而是在执行内联元素删除时如何处理不断变化的数组长度。这是一个 jsPerf,以便您可以将高效版本作为答案并将其与发布的其他答案进行比较。 jsperf.com/soq-iterate-over-an-array-and-remove 处理数组长度变化的规范方法是从数组的末尾开始并向后工作。或者,如果您删除了当前元素,则可以从当前位置向前工作并且不增加。相反,每次找到匹配项时,您的方法从第零个元素开始,从而反复遍历相同的元素。这是一个非常糟糕的算法,永远不应该使用。 好吧,这很奇怪——我试过了,而且(在这个小样本集上)它慢得多。我还不知道为什么。 jsperf.com/soq-iterate-over-an-array-and-remove/2 我稍微更改了测试用例 - 现在 fromIndex 用例的运行速度非常轻微...jsperf.com/soq-iterate-over-an-array-and-remove/3【参考方案6】:

从头开始!

var elements = [1, 5, 5, 3, 5, 2, 4];
for(var i = elements.length -1; i >= 0 ; i--)
    if(elements[i] == 5)
        elements.splice(i, 1);
    

【讨论】:

+1 用于从末尾开始,以避免由于 OP 提到的长度变化而跳过元素。 for (var i = elements.length; i--;) 可能是更常见的写法。 我希望我能不止一次地对此表示赞同。奥卡姆正在向你发送一个来自伟大彼岸的宇宙高五。 认真的吗?一个 O(n^2) 的答案,有 147 个赞成票,没有反对票?这是给你的反对票。 这不只是 O(n) 吗?它只循环整个数组一次。

以上是关于如何在 JavaScript 中迭代数组并删除元素 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Vue:从数组中删除第一个元素并迭代它

如何从javascript或jquery中的元素数组中删除特定元素

从Ruby中的数组中删除重复元素

JavaScript如何实现对数组元素的插入、删除、替换

javascript 删除并返回数组中的第一个元素

javascript 删除并返回数组中的最后一个元素