如何在单个循环中映射+过滤器



我以前在SO上问过这个问题,但我找不到问题/答案!

基本上我想创建这个:

Array.prototype.filterAndMap = function(){};

我可以像这样使用它的地方:

[1,2,3,4,5].filterAndMap(function(){
     if(i % 2 === 0){
        return i*2;
     }
});

以上将返回:

  [4,8]

我认为实现这一点的最佳方法是使用Array.prototype.reduce...但我不确定。

我试图避免的是遍历列表两次:

   [1,2,3,4,5].filter(function(){
         return i % 2 === 0;
    })
    .map(function(i){
         return i * 2;
    });

您可以迭代数组并连接值(如果有效(或空数组(如果无效(。

var array = [1, 2, 3, 4, 5],
    result = array.reduce(function(r, a) {
        return r.concat(a % 2 ? [] : 2 * a);
    }, []);
    
console.log(result);

ES6

var array = [1, 2, 3, 4, 5],
    result = array.reduce((r, a) => r.concat(a % 2 ? [] : 2 * a), []);
    
console.log(result);

这两种方法(.map.filter(结合起来是不可能的,因为.filter不对元素执行任何逻辑,并且.map总是从给定数组返回每个元素。Hovewer 您可以尝试.reduce方法,仅返回满足给定条件的元素。

const arr = [1,2,3,4,5];
const r = arr.reduce((s, a) => (a % 2 ? null : s.push(a * 2), s), []);
console.log(r);

reduce肯定会做到这一点:

[1,2,3,4,5].reduce((arr, cur) => { 
   if(cur % 2 == 0){
      arr.push(cur * 2); 
   }
   return arr;
}, []);   // => [2, 4]

正如你所说,reduce可能是要走的路:

const myArray = [1, 2, 3, 4, 5];
function mapAndFilter(array, filterFunc, mapFunc) {
    return array.reduce((p, c) => {
        if (filterFunc(c)) p.push(mapFunc(c));
        return p;
    }, []);
}
const mapFilteredArray = mapAndFilter(myArray, x => x % 2 === 0, x => x*2);
console.log(mapFilteredArray);

根据需要调整该功能以继续使用阵列原型。

根据您的示例代码,您的问题已以特定方式得到解答。

如果您尝试完成的是filtermap的通用函数(尽管它不是map,它是一个reduce(,这就是您正在寻找的:

var filterAndReduce = function(arr, filterFn, fn) {
  return arr.reduce(function(r, a) {
        return r.concat(filterFn(a) ? [] : fn(a));
  }, []);
};

您将以这种方式使用它:

filterAndReduce([1,2,3,4,5], function(i) {
     return i % 2;
},
function(i) {
    return i * 2
});

最新更新