如何删除JS中参数指定的数组中的元素?

时间:2016-01-05 05:38:29

标签: javascript arrays

我正在处理一个赋值,我在其中提供了一个数组和不同数量的参数。我必须删除初始数组中与这些参数值相同的所有值。这是我的代码:

function destroyer(arr) {
  for(var i = 1; i < arguments.length; i++)
  {
      for(var j = 0; j < arr.length; j++)
      {
          if(arguments[i] == arr[j])
          {
              arr.splice(j, 1);
          }
      }
  }
  return arr;
}

destroyer([3, 5, 1, 2, 2], 2, 3, 5)

我得到了一些数组和参数模式的正确输出但是对于上面的例子,它应该只输出[1]但我的代码输出[1,2]。任何帮助,将不胜感激。感谢。

3 个答案:

答案 0 :(得分:1)

当您执行.splice()删除项目时,它会将元素向下移动到数组中的某个位置之后,这将导致您的for循环错过下一个元素是一场比赛。您可以通过在删除项目之后递减for循环索引来解决此问题,或者(我最喜欢的)您可以从后向前迭代数组,然后.splice()不会影响任何将来的迭代。

使用您的通用代码结构,这是减量解决方案:

function destroyer(arr) {
  for(var i = 1; i < arguments.length; i++)
  {
      for(var j = 0; j < arr.length; j++)
      {
          if(arguments[i] == arr[j])
          {
              arr.splice(j, 1);
              --j;
          }
      }
  }
  return arr;
}

var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
document.write(JSON.stringify(result));

使用您的通用代码结构,这是反向迭代解决方案:

function destroyer(arr) {
  for(var i = 1; i < arguments.length; i++)
  {
      for(var j = arr.length - 1; j >= 0; j--)
      {
          if(arguments[i] == arr[j])
          {
              arr.splice(j, 1);
          }
      }
  }
  return arr;
}

var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
document.write(JSON.stringify(result));

您还可以使用其他数组助手函数来利用更多本机数组功能:

function destroyer(arr) {
    var removes = Array.prototype.slice.call(arguments, 1);
    return arr.filter(function(item) {
        return removes.indexOf(item) === -1;
    });
}

var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
document.write(JSON.stringify(result));

使用ES6套装获得更高的潜在效率:

    function destroyer(arr) {
        var removes = new Set(Array.prototype.slice.call(arguments, 1));
        return arr.filter(function(item) {
            return !removes.has(item);
        });
    }

    var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
    document.write(JSON.stringify(result));

仅供参考,在前面的代码示例中,我试图这样做:

var removes = new Set(arguments);

因为它看起来更干净,并且在IE和Chrome中运行良好,但Firefox中的一个错误使它无法在那里工作。 ES6中的arguments应该是一个可以传递给Set构造函数的迭代,但Firefox尚未正确实现。正在处理该主题的open Firefox bug。所以,我支持这个代码示例,将副本复制到一个真正的数组中,然后将数组传递给构造函数。

另一种可能性是使用ES6休息参数:

function destroyer(arr, ...items) {
  var removes = new Set(items);
  return arr.filter(function(item) {
    return !removes.has(item);
  });
}

var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
document.write(JSON.stringify(result));

答案 1 :(得分:0)

制作它(使用indexOfwhile循环)

function destroyer(arr) {
  for(var i = 1; i < arguments.length; i++)
  {
          var index = arr.indexOf( arguments[i] );
          while( index != -1 )
          {
              arr.splice(index, 1);
              console.log(arr);
              index = arr.indexOf( arguments[i] );
          }
  }
  return arr;
}

您需要一次又一次地检查,而不是只检查一次,除非index-1

答案 2 :(得分:0)

使用相同的练习,即使说明说明使用 Arguments 对象,此解决方案也有效:

function destroyer(arr, ...valsToRemove) {
return arr.filter(elem => !valsToRemove.includes(elem));
}