代码之家  ›  专栏  ›  技术社区  ›  Vincent Robert

用javascript中的array.map删除元素

  •  59
  • Vincent Robert  · 技术社区  · 18 年前

    我想使用 map() 功能。以下是代码段:

    var filteredItems = items.map(function(item)
    {
        if( ...some condition... )
        {
            return item;
        }
    });
    

    问题是,筛选出的项仍然使用数组中的空间,我希望完全清除它们。

    有什么想法吗?

    编辑:谢谢,我忘了 filter() 我想要的其实是 过滤器() 然后一个 MAP() .

    伊迪丝2:谢谢你的指点 MAP() 过滤器() 并没有在所有浏览器中实现,尽管我的特定代码并不打算在浏览器中运行。

    6 回复  |  直到 7 年前
        1
  •  77
  •   olliej    18 年前

    你应该使用 filter 方法,而不是映射,除非除了筛选之外,还希望改变数组中的项。

    如。

    var filteredItems = items.filter(function(item)
    {
        return ...some condition...;
    });
    

    [编辑:当然可以 sourceArray.filter(...).map(...) 同时过滤和变异]

        2
  •  28
  •   Kyle Baker    7 年前

    我刚才写了一个答案,我的意见改变了。我建议检查一下我的 blog post 这就扩展了这个主题,并更好地解释了它。在备选方案的末尾,它还提供了一个JSPERF比较。

    TL;DR是: 为了完成您所要求的(在一个函数调用中过滤和映射),您应该使用 Array.reduce() . 然而, 更可读 通常更快 2 方法是只使用过滤器和链接在一起的映射:

    [1,2,3].filter(num => num > 2).map(num => num * 2)

    下面是如何 数组 工作,以及如何在一次迭代中使用它来完成过滤和映射。如果这太过浓缩,我强烈建议你看看上面链接的博客文章,这是一个更友好的介绍,有明确的例子和进展。

    你给reduce一个参数,它是一个(通常是匿名的)函数。

    那个匿名函数 接受两个参数——一个(像传递给map/filter/foreach的匿名函数)是要操作的迭代器。但是,对于传递给reduce的匿名函数还有另一个参数,即那些函数不接受,也就是说 在函数调用之间传递的值,通常称为 备忘录 .

    注意,虽然array.filter()只接受一个参数(一个函数),array.reduce()也接受一个重要的(尽管可选)第二个参数:“memo”的初始值将作为其第一个参数传递给匿名函数,随后可以在函数调用之间进行变异和传递。(如果未提供,则第一个匿名函数调用中的“memo”默认为第一个迭代器,“迭代器”参数实际上是数组中的第二个值)

    在我们的例子中,我们将首先传递一个空数组,然后根据我们的函数选择是否将迭代器注入到数组中——这是过滤过程。

    最后,我们将在每个匿名函数调用上返回“array in progress”,reduce将获取该返回值并将其作为参数(称为memo)传递给下一个函数调用。

    这允许过滤器和映射在一个迭代中发生,从而将所需的迭代次数减少一半。:)

    有关更完整的解释,请参阅 MDN 或者上面的链接。:)

    reduce调用的基本示例:

    let array = [1,2,3];
    const initialMemo = [];
    
    array = array.reduce((memo, iteratee) => {
        // if condition is our filter
        if (iteratee > 1) {
            // what happens inside the filter is the map
            memo.push(iteratee * 2); 
        }
    
        // this return value will be passed in as the 'memo' argument
        // to the next call of this function, and this function will have
        // every element passed into it at some point.
        return memo; 
    }, initialMemo)
    
    console.log(array) // [4,6], equivalent to [(2 * 2), (3 * 2)]
    

    更简洁的版本:

    [1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])
    

    注意,第一个迭代器不大于一个,所以被过滤了。还要注意草签备忘录,它的名字只是为了让它的存在变得清晰并引起人们的注意。再次,它作为“memo”传递给第一个匿名函数调用,然后匿名函数的返回值作为“memo”参数传递给下一个函数。

    备忘录的另一个典型用例是返回数组中最小或最大的数字。例子:

    [7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val)
    // ^this would return the largest number in the list.
    

    关于如何编写自己的reduce函数的示例(我发现,这通常有助于理解这些函数):

    test_arr = [];
    
    // we accept an anonymous function, and an optional 'initial memo' value.
    test_arr.my_reducer = function(reduceFunc, initialMemo) {
        // if we did not pass in a second argument, then our first memo value 
        // will be whatever is in index zero. (Otherwise, it will 
        // be that second argument.)
        const initialMemoIsIndexZero = arguments.length < 2;
    
        // here we use that logic to set the memo value accordingly.
        let memo = initialMemoIsIndexZero ? this[0] : initialMemo;
    
        // here we use that same boolean to decide whether the first
        // value we pass in as iteratee is either the first or second
        // element
        const initialIteratee = initialMemoIsIndexZero ? 1 : 0;
    
        for (var i = initialIteratee; i < this.length; i++) {
            // memo is either the argument passed in above, or the 
            // first item in the list. initialIteratee is either the
            // first item in the list, or the second item in the list.
            memo = reduceFunc(memo, this[i]);
        }
    
        // after we've compressed the array into a single value,
        // we return it.
        return memo;
    }
    

    例如,真正的实现允许访问索引之类的东西,但我希望这能帮助您对索引的要点有一种简单的感觉。

        3
  •  11
  •   Patrick    18 年前

    这不是地图的作用。你真的想要 Array.filter . 或者,如果您真的想从原始列表中删除元素,则需要使用for循环来强制执行。

        4
  •  3
  •   Markus Safar    10 年前

    但是,您必须注意 Array.filter 并非所有浏览器都支持,因此,必须进行原型设计:

    //This prototype is provided by the Mozilla foundation and
    //is distributed under the MIT license.
    //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
    
    if (!Array.prototype.filter)
    {
        Array.prototype.filter = function(fun /*, thisp*/)
        {
            var len = this.length;
    
            if (typeof fun != "function")
                throw new TypeError();
    
            var res = new Array();
            var thisp = arguments[1];
    
            for (var i = 0; i < len; i++)
            {
                if (i in this)
                {
                    var val = this[i]; // in case fun mutates this
    
                    if (fun.call(thisp, val, i, this))
                       res.push(val);
                }
            }
    
            return res;
        };
    }
    

    这样做,你可以原型任何你可能需要的方法。

        5
  •  3
  •   Mulan    9 年前

    我把这个答案放在这里是因为这个页面上共享的polyfill非常糟糕

    function reduce(f, y, xs, context) {
      var acc = y;
      for (var i = 0, len = xs.length; i < len; i++)
        acc = f.call(context, acc, xs[i], i, xs);
      return acc;
    }
    
    function reduce1(f, xs, context) {
      if (xs.length === 0)
        throw Error('cannot reduce empty array without initial value');
      else
        return reduce(f, xs[0], xs.slice(1), context);
    }
    
    function map(f, xs, context) {
      return reduce(function(acc, x, i) {
        return acc.concat([
          f.call(context, x, i, xs)
        ]);
      }, [], xs);
    }
    
    function filter(f, xs, context) {
      return reduce(function(acc, x, i) {
        if (f.call(context, x, i, xs))
          return acc.concat([x]);
        else
          return acc;
      }, [], xs);
    }
    

    扩展原型

    if (Array.prototype.reduce === undefined) {
      Array.prototype.reduce = function(f, initialValue, context) {
        if (initialValue === undefined)
          return reduce1(f, this, context);
        else
          return reduce(f, initialValue, this, context);
      };
    }
    
    if (Array.prototype.map === undefined) {
      Array.prototype.map = function(f, context) {
        return map(f, this, context);
      };
    }
    
    if (Array.prototype.filter === undefined) {
      Array.prototype.filter = function(f, context) {
        return filter(f, this, context);
      };
    }
    
        6
  •  2
  •   vsync    10 年前
    var arr = [1,2,'xxx','yyy']
    
    arr = arr.filter(function(e){ return e != 'xxx' });
    
    arr  // [1, 2, "yyy"]
    
    推荐文章