javascript-条件下删除数组元素


77

我想知道我将如何在javascript中实现一种方法,该方法将删除清除特定条件的数组的所有元素。(最好不使用jQuery)

例如

ar = [ 1, 2, 3, 4 ];
ar.removeIf( function(item, idx) {
    return item > 3;
});

上面的代码将遍历数组中的每个项目,并删除所有return true符合条件的项目(在示例中,项目> 3)。

我刚刚开始使用javascript,想知道是否有人知道一种有效的简短方法来完成此任务。

-更新-

如果条件也可以对对象属性起作用,那也将很好。

例如

ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
ar.removeIf( function(item, idx) {
    return item.str == "c";
});

该项目将在哪里删除 item.str == "c"

- UPDATE2 -

如果索引条件也能正常工作,那就太好了。

例如

ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
ar.removeIf( function(item, idx) {
    return idx == 2;
});

Answers:


48

Array如果filter不适合您,则可以添加自己的方法来执行类似的操作。

Array.prototype.removeIf = function(callback) {
    var i = 0;
    while (i < this.length) {
        if (callback(this[i], i)) {
            this.splice(i, 1);
        }
        else {
            ++i;
        }
    }
};

对我来说,这是JavaScript最酷的功能之一。伊恩指出了一种更有效的方法来做同样的事情。考虑到它是JavaScript,每一点都有帮助:

Array.prototype.removeIf = function(callback) {
    var i = this.length;
    while (i--) {
        if (callback(this[i], i)) {
            this.splice(i, 1);
        }
    }
};

这样一来,您无需再担心更新length或捕获下一个项目,因为您的工作方式向左而不是向右。


谢谢,效果很好。我喜欢这种方式如何考虑索引在迭代过程中通过拼接的变化。
dk123

4
有点混乱。尝试jsfiddle.net/n8JEy/4-您没有i将回调传递为第二个参数
Ian

@Ian我倾向于可读性,但是您的解决方案肯定更有效。我还添加了索引作为第二个参数(由于本来没有使用它,所以本来只是忽略了它,我以为他不需要它)。
pickypg

@ dk123作为JavaScript的新手,您可以自由地控制自己认为合适的此类回调的参数,并且只要信息可用就可以向其添加所需的任何内容(例如,可以使用以下命令添加当前数组的长度)this.length作为第三个参数(如果您有一些偏好)。
pickypg

@pickypg没问题!确实是这样 我想我只是没有找到以这种方式分离逻辑的理由,但是显然可以。而“混乱”是一个错误的术语。没意识到第二个参数,只是想指出一点:)
Ian

91

您可以使用数组过滤器方法

代码如下所示:

ar = [1, 2, 3, 4];
ar = ar.filter(item => !(item > 3));
console.log(ar) // [1, 2, 3]


41
如果您翻译!(item > 3)成人类语言,它将是item <= 3
Miha_x64

4
请记住,Array.filter方法将创建一个新数组。如果您在另一个变量中引用数组,则引用将在之后被破坏: ar1 = [1, 2, 3, 4]; ar2 = ar1; ar1 = ar1.filter(item => !(item > 3)); console.log(ar1); console.log(ar2);
Atilla Baspinar

36

您可以使用Array.filter(),执行相反的操作:

ar.filter(function(item, idx) {
    return item <= 3;
});

2
IE8或更低版本不支持此功能。您还应该否定原始表达式,或者应该为<=
pickypg

16
Array.filter()是否不返回带有过滤元素的新数组?有什么可以从数组中删除元素的吗?
dk123

@ dk123:没有任何预制的。您必须编写一个for循环
。– Blender

制作新阵列的Array.filter速度可能比手动拼接给定阵列的速度更快。
Casey Chu

@Blender这很有趣。我发誓我最近只是研究了两者之间的比较,事实恰恰相反。我的愚蠢评论已删除。感谢您提供证据:)
Ian

5

您可以使用lodash.remove

var array = [1, 2, 3, 4];
var evens = _.remove(array, function(n) {
  return n % 2 == 0;
});

console.log(array);
// => [1, 3]

console.log(evens);
// => [2, 4]

2

我喜欢这些问题,也喜欢与我不同的版本... :)

Array.prototype.removeIf = function(expression) {
   var res = [];
    for(var idx=0; idx<this.length; idx++)
    {
      var currentItem = this[idx];
        if(!expression(currentItem))
        {
            res.push(currentItem);
        }
    }
    return res;
}

ar = [ 1, 2, 3, 4 ];
var result = ar.removeIf(expCallBack);


console.log(result);
function expCallBack(item)
{
    return item > 3;
}

1
您是否可以稍微修改(或添加另一个方法)代码以实际删除元素,而不是返回新数组?谢谢回复。
dk123 2013年

3
谁反对这个错呢。这是所有方法中最好的性能最佳答案。通过@Blender jsperf.com/splice-vs-filter检查测试。在最新版的Firefox中,它至少快2倍,快15倍
议会

2

如果条件也适用于对象属性,只需编写以下示例

var ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
var newArray = [];
for (var i = 0, len = ar.length; i<len; i++) {
        if (ar[i].str == "b") 
        {newArray.push(ar[i]);};
 };
console.log(newArray);

参见示例在线示例


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.