Javascript相当于Clojure""减少"或python的itertools.accumulate

时间:2015-10-21 01:39:58

标签: javascript python clojure functional-programming reduce

是否存在类似于Clojure""#34;#34;函数或Python的pause pause pause pause pause pause pause resume resume resume resume resume resume resume resume pause pause pause pause pause pause pause resume resume resume resume resume resume resume resume pause pause pause pause pause pause pause resume resume resume resume resume resume resume resume ?换句话说,给定一个数组itertools.accumulate和一个函数[x_0, x_1, x_2 ... x_n-1],它将返回一个长度为f(prev, next)的数组,其值为:

n

我在下面模拟了所需的行为:

[x_0, f(x_0, x_1), f(f(x_0, x_1), x_2)... f(f(f(...)), x_n)]

显示:

function accumsum(prev, next) {
    last = prev[prev.length - 1] || 0;
    prev.push(last + next);
    return prev;
}

var x = [1, 1, 1, 1];
var y = x.reduce(accumsum, []);
var z = y.reduce(accumsum, []);

console.log(x);
console.log(y);
console.log(z);

但是我想知道是否有办法写一些更简单的东西,比如

[ 1, 1, 1, 1 ]
[ 1, 2, 3, 4 ]
[ 1, 3, 6, 10 ]

如果没有,在JavaScript中使用比我写的更惯用的方法吗?

3 个答案:

答案 0 :(得分:3)

var a = [1, 1, 1, 1];
var c = 0;
a.map(function(x) { return c += x; })
// => [1, 2, 3, 4]

a.reduce(function(c, a) {
  c.push(c[c.length - 1] + a);
  return c;
}, [0]).slice(1);
// => [1, 2, 3, 4]

我个人会使用第一个。

编辑:

  

有没有办法做你的第一个建议,不要求我有一个随机的全局变量(在这种情况下是c)漂浮?如果我忘了将c重新初始化为0,那么我第二次写a.map(...)就会给出错误的答案。

当然 - 你可以封装它。

function cumulativeReduce(fn, start, array) {
  var c = start;
  return array.map(function(x) {
    return (c = fn(c, x));
  });
}
cumulativeReduce(function(c, a) { return c + a; }, 0, [1, 1, 1, 1]);
// => [1, 2, 3, 4]
c
// => ReferenceError - no dangling global variables

答案 1 :(得分:0)

对于子孙后代,如果您处于使用旧版JavaScript的情况,或者无法访问Underscore

从头开始实施起来并不困难,具有一定的教育价值。

以下是一种方法:

function reduce(a, fn, memo) {
  var i;
  for (i = 0; i < a.length; ++i) {
    if ( typeof memo === 'undefined' && i === 0 ) memo = a[i];
    else memo = fn(memo, a[i]);
  }
  return memo;
}

此外,其他更高阶的函数可以用reduce来编写,例如: &#34; map&#34;,显示在这里:

function map(a, fn) {
  return reduce(a, function(memo, x) {
    return memo.concat(fn(a));
  }, []);
}

作为参考,映射的等效命令(和更快)版本将是:

function map2(a, fn) {
  var newA = [], i;
  for (i = 0; i < a.length; ++i) {
    newA.push(fn(a[i]));
  }
  return newA;
}

答案 2 :(得分:0)

我写了一个无状态版本

function reductions(coll, reducer, init) {
  if (!coll.length) {
    return [init]
  }
  if (init === undefined) {
    return reductions(_.drop(coll, 1), reducer, _.first(coll))
  }
  return [init].concat(reductions(_.drop(coll, 1), reducer, reducer(init, _.first(coll))))
}