【问题标题】:javascript - remove array element on conditionjavascript - 根据条件删除数组元素
【发布时间】:2013-04-06 10:23:39
【问题描述】:

我想知道如何在 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;
});

【问题讨论】:

    标签: javascript


    【解决方案1】:

    如果您需要删除一个项目,并且您确定该项目存在,您可以使用这个单行:

    ar.splice(ar.findIndex(el => el.id === ID_TO_REMOVE), 1);
    
    // or with custom method:
    let ar = [ {id:1, str:"a"}, {id:2, str:"b"}, {id:3, str:"c"}, {id:4,str:"d"} ];
    ar.removeById = id => ar.splice(ar.findIndex(el => el.id === id), 1);
    ar.removeById(ID_TO_REMOVE);
    

    http://jsfiddle.net/oriadam/72kgprw5/

    仅限 ES6

    【讨论】:

    • splice() + findIndex() 并不比 filter() 删除删除的值快。还是在某些情况下?
    【解决方案2】:

    您可以使用Array filter method

    代码如下所示:

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

    【讨论】:

    • 如果你把!(item > 3)翻译成人类语言,那就是item <= 3
    • 请记住 Array.filter 方法会创建一个新数组。如果您在另一个变量中引用您的数组,该引用将在之后被破坏:ar1 = [1, 2, 3, 4]; ar2 = ar1; ar1 = ar1.filter(item => !(item > 3)); console.log(ar1); console.log(ar2);
    • @Miha_x64 在 JavaScript 中,!(item > 3)item <= 3 并不完全相同。如果该数组包含 undefined 项,!(item > 3) 将为真,而item <= 3 将为假。
    • @Rudey,不错的收获!
    【解决方案3】:

    使它成为一个带有箭头功能的单行:

    ar = ar.filter(i => i > 3);
    

    【讨论】:

      【解决方案4】:

      您可以使用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]
      

      【讨论】:

        【解决方案5】:

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

        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);
        

        查看示例Live Example

        【讨论】:

          【解决方案6】:

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

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

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

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

          这样就无需担心更新length 或捕捉下一个项目,因为您按自己的方式工作而不是向右。

          【讨论】:

          • 谢谢,效果很好。我喜欢在迭代过程中考虑到通过拼接的索引变化。
          • 这有点乱。尝试jsfiddle.net/n8JEy/4 - 你没有将i 作为第二个参数传递给回调
          • @Ian 我更喜欢可读性,但您的解决方案肯定更有效。我还添加了索引作为第二个参数(由于没有使用它,所以最初忽略它,我假设他不需要它)。
          • @dk123 作为 JavaScript 的新手,您可以随意控制此类回调的参数,只要信息可用,您就可以添加任何您想要的参数(例如,如果你有一些倾向,你可以使用this.length 作为第三个参数添加当前数组的长度。
          • 修改预定义类的原型是有风险的。应该只以 polyfill-ish 方式完成,即。 e.添加已在规范中声明但尚未由浏览器实现的成员。感谢您的解决方案,我将其用作本地功能。
          【解决方案7】:

          我喜欢这类问题,只是和我的版本不同...... :)

          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;
          }
          

          【讨论】:

          • 您能否修改(或添加另一种方法)您的代码以实际删除元素而不是返回新数组?感谢您的回复。
          • 谁投反对票这么错误。这是所有答案中表现最好的答案。通过@Blender jsperf.com/splice-vs-filter 检查测试。在最新版本的 Firefox 中,速度至少快 2 倍,最多快 15 倍
          【解决方案8】:

          您可以使用Array.filter(),它的作用正好相反:

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

          【讨论】:

          • 作为提示,IE8 或更低版本不支持。您还应该否定原始表达式,或者它应该是&lt;=
          • Array.filter() 不返回一个包含过滤元素的新数组吗?有什么东西只是从数组中删除元素吗?
          • @dk123:没有任何预制。你必须写一个for循环。,
          • 使用Array.filter 创建一个新数组可能比手动拼接给定数组更快。
          • @Blender 这很有趣。我发誓我最近刚刚研究了一些比较这两者的东西,结果恰恰相反。我的愚蠢评论被删除。感谢您提供证明:)
          猜你喜欢
          • 2020-12-13
          • 1970-01-01
          • 2011-11-29
          • 2022-11-17
          • 2018-10-12
          • 1970-01-01
          • 2022-12-18
          • 2017-08-31
          相关资源
          最近更新 更多