使用Filter和Loop从Javascript数组中删除多个值

4
我是新来的,需要帮助编写一个名为destroyer()的函数,用于从一个数组中删除多个值。
destroyer() 函数将数组和额外的数字作为参数传递。其目的是从数组中移除这些数字。
例如:
destroyer([1, 2, 3, 1, 2, 3], 2, 3) 

输出:[1,1]
destroyer(["tree", "hamburger", 53], "tree", 53) 

输出:["汉堡包"]

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

输出:

输出:[]

注意:示例仅显示要删除的2个附加数字。但是,destroyer()函数应该能够删除任意数量的值(即4、5或6个参数)。

然而,我的代码没有产生相同的结果。具体来说,使用console.log,我发现我的filterer函数没有正确循环。

1)有人可以帮我调试吗?

2)有更好的编写此函数的方法吗?

非常感谢!!!

function destroyer() {

  var args = Array.prototype.slice.call(arguments); 

  var itemToRemove = args.slice(1);
  console.log(itemToRemove);
  var newArr = args[0];
  console.log(newArr);

  function filterer(value) { 

    for (var i = 0; i < itemToRemove.length; i++) {
      console.log(i);
      console.log(itemToRemove[i]);
      if (value != itemToRemove[i]) {
        return value;
      }
    } 
   }

  return newArr.filter(filterer);
}

如果您告诉我们删除的标准,而不是发布神秘的示例,那么帮助您可能会更容易。 - adeneo
在第一个参数中,他传递了一个数组,在接下来的参数中,他想要删除的值。 - h0ch5tr4355
你是否总是传递两个值来进行删除?或者可以传递更多的值,例如 destroyer([1, 2, 3, 1, 2, 3], 2,4, 3) - Grundy
它可以是任意数量的值,例如在您的示例中要删除3个值。 - Neong
我闻到了freeCodeCamp的味道 ;D - Leo
7个回答

4
你的filterer函数可以更简单:
function filterer (value) {
    return itemToRemove.indexOf(value) === -1;
}

@Neong,请注意,在大数组上,如果有许多要删除的项,则可能不会很快。 - Grundy

0

Array.prototype.indexOf() 在时间复杂度上与对象属性查找相比可能效率较低。我建议循环遍历附加参数一次,并使用目标元素作为键构建一个对象,然后您可以检查传递给 Array.prototype.filter() 的过滤回调函数中给定的值是否是目标值。

function destroyer() {
    var arr = arguments.length && arguments[0] || [];
    var targets = {};
    for (var i = 1; i < arguments.length; i++) {
        targets[arguments[i]] = true;
    }
    return arr.filter(function (x) {
        return targets[x] === undefined;
    });
}

这种方法的一个缺点是,并不是所有的JS值都可以作为对象的有效属性,因为属性必须是字符串。在这种情况下,你只是将数字作为键使用,而这些数字会被隐式转换为字符串。

1
我认为在这种情况下最好使用 targets[arguments[i]] = true 或者类似的方式,在过滤函数中使用 targets[x] === undefined,因为 hasOwnProperty 是更复杂且比较 _undefined_ 更慢的函数。 - Grundy
1
@Grundy 已经注意到了,我已经编辑了答案。感谢您的建议。 - Shashank
1
谢谢Shashank和@Grundy的帮助。我花了一些时间才理解这个方法;) 感谢您的观点! - Neong

0
我们可以在filter()方法中向回调函数传递额外的参数作为参数。
function destroyer(arr) {
  return arr.filter(filterer(arguments)); // Pass arguments
}

function filterer(args) {
  return function(value) { // Actual filter function
    for (var i = 1; i < args.length; i++) {
      if (value === args[i]) // Seek
        return false; // Destroy
    }
    return true; // Otherwise keep
  };
}

这通过了freeCodeCamp | Basic Algorithm Scripting | 寻找并销毁的所有5个测试案例。


-1
以下代码将从数组中删除元素。它所删除的元素由任何额外参数定义。...remove是ES6功能,将额外参数聚合到单个数组中。
我将遍历...remove数组并从我们正在处理的主数组中删除该元素。
这是一个JSFiddle:https://jsfiddle.net/zzyopnnp/ 大多数浏览器不支持...extra_parameters,您可能需要使用arguments对象。
function removeIndex(array, index) {if(index>-1){array.splice(index, 1);}}

function destroyer(array, ...remove) {
    remove.forEach(function(elem, index) {
        removeIndex(array, index);
    });
};

var arr = ["tree", "hamburger", 53];
destroyer(arr, "tree", 53);
console.log(arr);

最好使用本地的Array.filter函数,而不是使用removeIndex - ykravv
@ykravch,filter 返回 new 数组,这里 - 改变了源数组。 - Grundy
@Grundy,是的,从问题看来,Neong想要的正是这种行为。 - ykravv
@ykravch,我不确定OP是否想要应用这个就地操作。 - Grundy
这样更简短,我不明白为什么不这样做。另外,如果你在服务器端使用nodeJS进行操作,你可以保证...args始终能够正常工作。 - Max
显示剩余2条评论

-1
一个简单的函数。
function filter(arr, arg1, arg2){

    var j = arr.length;
    while(j){

       if (arr.indexOf(arg1) > -1 || arr.indexOf(arg2) > -1){
          arr.splice(j - 1, 1);
       }
       j--
    }
}

如果应该有三个额外的参数呢?或者四个? :-) - Grundy
在他的需求中需要两个参数,我为此编写了这个函数。 - Azad
这只是一个示例,我认为。另外,为什么在每个循环迭代中都要进行两次 indexOf,而不是测试数组元素并在相等于 arg1 或 arg2 时执行 splice? - Grundy
我在下面添加了另一个答案。 - Azad
抱歉我表达不够清楚,需要移除的数值可以是任意数量 -- 2、3、4、5等等。 - Neong
请查看我下面的另一个答案。 - Azad

-1

对于多个参数

一个简单的函数

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

你可以使用以下方式调用此函数,无需参数:

 filter([1,2,3,4,5,6,7,8,9], 1, 3, 5); //return [2,4,6,7,8,9]
 filter([1,2,3,4,5,6,7,8,9], 1); //return [2,3,4,5,6,7,8,9]

你不需要在...,arg1, arg2, arg3, arg4中使用,function filter(arr)就足够了。 - Grundy
但现在看起来,最大参数数似乎是4。 - Grundy
好的,那么我来编辑一下,用户应该这样调用:filter([1,2,3,4,5,6,7,8,9], 1, 3, 5); - Azad
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/93042/discussion-between-grundy-and-azzi。 - Grundy
检查一下 OP 的这个示例:destroyer([1, 2, 3, 1, 2, 3], 2, 3) 应该返回 [1,1],但是你的代码返回了 [1, 1, 2, 3] - Grundy
显示剩余6条评论

-1

这里有一些非常好的答案,但你可以通过以下方式更加简洁地完成它:请记住,在过滤方法中你有一个对象选项可以在回调函数中使用,本例中我像这样使用:arguments[i],以便检查参数数组中的每个值。

function destroyer(arr) {

   for(var i = 1; i < arguments.length; i++){
     arr = arr.filter(isIn, arguments[i]);
   } 

   function isIn(element,index, array){
      if (element != this){
         return element;
      }
   }  
   return arr;
}

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