"过滤器"或者" Map"使用不同测试的相同数组没有多次循环?

时间:2014-06-17 03:15:09

标签: javascript

例如我有

var nums = [1,2,3,4,5,6,7,8,9];

有没有办法写这个:

var multiplesOf2 = nums.filter(...)
var multiplesOf3 = nums.filter(...)
var greaterThan7 = nums.filter(...)

并且与

一样高效
var multiplesOf2 = [], multiplesOf3 = [], greaterThan7  = [];
nums.forEach(function (num) {
  if (...) { multiplesOf2.push(num); }
  if (...) { multiplesOf3.push(num); }
  if (...) { greatherThan7.push(num); }
})

3 个答案:

答案 0 :(得分:1)

我只能猜测你希望.forEach()更清洁一点。如果您认为有帮助,可以使用.reduce()

var res = nums.reduce(function (obj, num) {
  if (...) { obj[2].push(num); }
  if (...) { obj[3].push(num); }
  if (...) { obj[7].push(num); }
  return obj;
}, {2:[],3:[],7:[]});

在ECMAScript 6中,您可以使用解构赋值将结果分配给各个变量。

let {2:two, 3:three, 7:seven} = nums.reduce(function (obj, num) {
  if (...) { obj[2].push(num); }
  if (...) { obj[3].push(num); }
  if (...) { obj[7].push(num); }
  return obj;
}, {2:[],3:[],7:[]});

答案 1 :(得分:1)

你需要测试性能,但是如果你想传入函数

,也许这样的东西会起作用
function filters(list /* test, test, test*/) {
    var i, j, arr = [], tests;
    tests = Array.prototype.slice.call(arguments, 1);
    j = tests.length;
    for (i = 0; i < j; ++i) arr[i] = [];
    list.forEach(function (element, index, array) {
        var i;
        for (i = 0; i < j; ++i) 
            if (tests[i](element, index, array))
                arr[i].push(element);
    });
    return arr;
}

filters(
    [1, 2, 3, 4, 5, 6, 7, 8, 9], // first arg the Array
    function (e) {return 0 === e % 2;}, // any number of tests to filter
    function (e) {return 0 === e % 3;},
    function (e) {return e > 7;}
);
/*
[
    [2, 4, 6, 8],
    [3, 6, 9],
    [8, 9]
]
*/

答案 2 :(得分:1)

这是一种方法:

var LazyArray = defclass({
    constructor: function (xs) {
        this.xs = xs;
        this.fs = [];
    },
    iterate: function () {
        var xs = this.xs, m = xs.length;
        var fs = this.fs, n = fs.length;

        for (var i = 0; i < m; i++) {
            var x =  xs[i];

            for (var j = 0; j < n; j++) {
                var f = fs[j], p = f(x, i, xs);
                if (p) fs.splice(j--, 1), n--;  // break out of the loop
            }
        }

        fs.length = 0;
    },
    filter: function (f) {
        var ys = [];

        this.fs.push(function (x) {
            if (f(x)) ys.push(x);
        });

        return ys;
    }
});

以下是您将如何使用它:

var nums = new LazyArray([1,2,3,4,5,6,7,8,9]);

var multiplesOf2 = nums.filter(...);
var multiplesOf3 = nums.filter(...);
var greaterThan7 = nums.filter(...);

nums.iterate();

但请注意,表现方面并没有真正的好处。如果输入数组包含m项,并且nfilter次调用,那么:

  1. 传统上,您会遍历mn次。
  2. 在这种情况下,您循环遍历n迭代器m次。
  3. 在任何一种情况下,时间复杂度为O(m * n)。除非您跳过一些使用严格评估不必要的计算,否则懒惰评估没有任何实际好处。

    P.S。您可以使用LazyArraymap等功能扩展reduce课程。


    修改:我忘记了defclass的定义:

    function defclass(prototype) {
        var constructor = prototype.constructor;
        constructor.prototype = prototype;
        return constructor;
    }
    

    那是所有人。