簡體   English   中英

Javascript相當於Clojure的“reductions”或python的itertools.accumulate

[英]Javascript equivalent to Clojure's “reductions” or python's itertools.accumulate

有沒有相當於Clojure的“reductions”函數或Python的itertools.accumulate的JavaScript? 換句話說,給定一個數組[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 ]

但我想知道是否有辦法寫出更簡單的東西

[1, 1, 1, 1].reductions(function(prev, next) {return prev + next;});

如果沒有,在JavaScript中有沒有比我寫的更慣用的方法呢?

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

對於后代,如果您處於使用舊版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來編寫,例如“map”,如下所示:

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;
}

我寫了一個無狀態版本

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))))
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM