在javascript中创建累积和数组

时间:2013-12-09 17:48:10

标签: javascript arrays

这是我需要做的一个例子:

var myarray = [5, 10, 3, 2];

var result1 = myarray[0];
var result2 = myarray[1] + myarray[0];
var result3 = myarray[2] + myarray[1] + myarray[0];
var result4 = myarray[3] + myarray[2] + myarray[1] + myarray[0];

所以这一切都会输出5,15,18,20

但不是像这样写出所有的变种,我想要它说:

var result = arrayitem + the sum of any previous items 

这有意义吗?那可能吗?我怎么做?

22 个答案:

答案 0 :(得分:22)

Javascript' s reduce提供当前索引,此处非常有用:

var myarray = [5, 10, 3, 2];
var new_array = [];
myarray.reduce(function(a,b,i) { return new_array[i] = a+b; },0);
new_array // [5, 15, 18, 20]

答案 1 :(得分:14)

避免制作新数组的替代reduce方法:

var result = myarray.reduce(function(r, a) {
  r.push((r.length && r[r.length - 1] || 0) + a);
  return r;
}, []);

没有必要为每个结果重新排列子数组。

编辑同一件事的丑陋版本:

var result = myarray.reduce(function(r, a) {
  if (r.length > 0)
    a += r[r.length - 1];
  r.push(a);
  return r;
}, []);

答案 2 :(得分:6)

ES6阵列传播的另外两个选项

[1, 2, 3].reduce((a, x, i) => [...a, x + (a[i-1] || 0)], []); //[1, 3, 6]

[3, 2, 1].reduce((a, x, i) => [...a, a.length > 0 ? x + a[i-1] : x], []); //[3, 5, 6]

答案 3 :(得分:5)

Nina Scholz复制的一种优雅的解决方案,使用currying访问先前的值。

const cumulativeSum = (sum => value => sum += value)(0);

console.log([5, 10, 3, 2].map(cumulativeSum));

cumulativeSum是函数value => sum += value,其中sum初始化为零。每次调用sum时,都会更新RewriteEngine on RewriteCond $1 !^(index\.php|public|\.txt) RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?$1 ,并且下次调用{input [n]]时,它将等于先前的值(output [n-1])。

答案 4 :(得分:4)

使用ES6的简单解决方案



let myarray = [5, 10, 3, 2];
    let new_array = [];  
    myarray.reduce( (prev, curr,i) =>  new_array[i] = prev + curr , 0 )
    console.log(new_array);




了解更多信息Array.reduce()

Arrow function

答案 5 :(得分:3)

this solution

怎么样?
var new_array = myarray.concat(); //Copy initial array

for (var i = 1; i < myarray.length; i++) {
  new_array[i] = new_array[i-1] + myarray[i];
}

console.log(new_array);

PS:您也可以使用原始数组。我只是复制它,以防我们不想污染它。

答案 6 :(得分:1)

另一个带有reduce和concat的干净的单行解决方案

var result = myarray.reduce(function(a,b,i){ return i === 0 ?  [b]: a.concat(a[i-1]+b);},0);
//[5, 10, 3, 2] => [5, 15, 18, 20]

答案 7 :(得分:1)

这个问题已经被其他人很好地回答了,但我也将解决方案留在这里。我试图保持简洁而不牺牲清晰度。

myarray.reduce((a, e, i) => {
  // a: Accumulator; e: current Element; i: current Index
  return a.length > 0 ? [...a, e + a[i - 1]] : [e];
}, []);

地图,过滤器,缩小,查找,某些等被低估了。

答案 8 :(得分:1)

/**
 * Turn an array of numbers to cumulative sum array
 * @param { Array } [1,2,3,4,5]
 * @return { Array } [1,3,6,10,15]
 */

const accumulate = (a, c) => a + c

const cusum = arr => arr.map((v, i, data) => {
    return data.slice(0, i + 1).reduce(accumulate)
})

答案 9 :(得分:1)

使用array-reduce的简单功能。

TotalReturns

答案 10 :(得分:1)

我最初的ES6想法类似于Taeho和其他人的一些上述答案。

const cumulativeSum = ([head, ...tail]) =>
   tail.reduce((acc, x, index) => {
      acc.push(acc[index] + x);
      return acc
  }, [head])
console.log(cumulativeSum([-1,2,3])

解决方案执行:

n次查找,n - 1次总和和0次条件评估

我上面看到的大部分内容似乎都在使用:

n次查找,2n次总和,以及n次条件评估:

您也可以使用ie6安全js执行此操作。这可能更有效,因为您不必创建尾部扩展数组。

function cumulativeSum(a) {
    var result = [a[0]];
    var last = a[0];
    for (i = 1; i < a.length; i++) {
        last = last + a[i];
        result.push(last)
    }
    return result;
}
console.log(cumulativeSum([-1,2,3]))

答案 11 :(得分:1)

更通用(且更有效)的解决方案:

Array.prototype.accumulate = function(fn) {
    var r = [this[0]];
    for (var i = 1; i < this.length; i++)
        r.push(fn(r[i - 1], this[i]));
    return r;
}

Array.prototype.accumulate = function(fn) {
    var r = [this[0]];
    this.reduce(function(a, b) {
        return r[r.length] = fn(a, b);
    });
    return r;
}

然后

r = [5, 10, 3, 2].accumulate(function(x, y) { return x + y })

答案 12 :(得分:1)

使用for循环的简单解决方案

var myarray = [5, 10, 3, 2];

var output = [];
var sum = 0;

for(var i in myarray){
  sum=sum+myarray[i];
  output.push(sum)
}
console.log(output)

https://jsfiddle.net/p31p877q/1/

答案 13 :(得分:1)

使用reduce直接和非破坏性地构建结果。

a.reduce(function(r,c,i){ r.push((r[i-1] || 0) + c); return r }, [] );

答案 14 :(得分:0)

使用箭头函数代替函数,使用逗号运算符代替return,使用currentIndex减少回调。

[5, 10, 3, 2].reduce((r, a, i) => (r.push((i && r[i - 1] || 0) + a), r), []); // [ 5, 15, 18, 20 ]

答案 15 :(得分:0)

为了将cumsum保持在函数中直到完全构建,我在Matt's Answer上提供了这个小变体:

var cumsum = function(past_sums, new_value) {
  var last_sum = 1*past_sums.slice(-1);
  var new_sum = last_sum + new_value;
  return past_sums.concat([new_sum]);
}
var some_sums = [5, 10, 3, 2].reduce(cumsum, []);

以下是它的工作原理:

  • 第一个周期:
    • past_sums.slice(-1) === []
    • 1*past_sums.slice(-1) === 0
  • 除了最后一个周期外的所有周期:
    • cumsum返回[past_sumsnew_sum]作为下一个周期的past_sums
  • 最后一个周期:
    • cumsum返回[5, 15, 18, 20]作为输出数组some_sums

可以用更少的行写入:

var cumsum = function(sums, val) {
  return sums.concat([ val + 1*sums.slice(-1) ]);
}
var some_sums = [5, 10, 3, 2].reduce(cumsum, []);

使用箭头函数(Not for ≤IE11 or Opera Mini),我写这个:

var cumsum = (sums,val) => sums.concat([ val + 1*sums.slice(-1) ]);
var some_sums = [5, 10, 3, 2].reduce(cumsum, []);

答案 16 :(得分:0)

按键和排序数组返回已排序的obj !!!

var unsorted_obj = {
  "2016-07-01": 25,
  "2016-07-04": 55,
  "2016-07-05": 84,
  "2016-07-06": 122,
  "2016-07-03": 54,
  "2016-07-02": 43
};

var sort_obj = function(obj){
  var keys = [];
  var sorted_arr = [];
  var sorted_obj = {};

  for(var key in obj){
    if(obj.hasOwnProperty(key)){
      keys.push(key);
    }
  }

  keys.sort();

  jQuery.each(keys, function(i, key){
    sorted_obj[key] = obj[key];
    var val = obj[key];
    sorted_arr.push({
      idx: i,
      date: key,
      val: val
    })
  });

  return { sorted_obj: sorted_obj, sorted_arr: sorted_arr };

};

var sorted_obj = sort_obj(unsorted_obj).sorted_obj;
var sorted_arr = sort_obj(unsorted_obj).sorted_arr;

// sorted_arr = [{"idx":0,"date":"2016-07-01","val":25},{"idx":1,"date":"2016-07-02","val":43},{"idx":2,"date":"2016-07-03","val":54},...]
// sorted_obj = {"2016-07-01":25,"2016-07-02":43,"2016-07-03":54,...}

答案 17 :(得分:0)

守旧而简单:

let myarray = [5, 10, 3, 2], result = [];

for (let i = 0, s = myarray[0]; i < myarray.length; i++, s += myarray[i]) result.push(s);

console.log(result); // [5, 15, 18, 20]

答案 18 :(得分:0)

我需要保留结果并仅添加运行中的total属性。我有一个带有日期和收入的json对象,还想显示一个运行总计。

//i'm calculating a running total of revenue, here's some sample data
let a = [
  {"date":  "\/Date(1604552400000)\/","revenue":  100000 },
  {"date":  "\/Date(1604203200000)\/","revenue":  200000 },
  {"date":  "\/Date(1604466000000)\/","revenue":  125000 },
  {"date":  "\/Date(1604293200000)\/","revenue":  400000 },
  {"date":  "\/Date(1604379600000)\/","revenue":  150000 }
];

//outside accumulator to hold the running total
let c = 0;

//new obj to hold results with running total
let b = a
  .map( x => ({...x,"rtotal":c+=x.revenue}) )
  
//show results, use console.table if in a browser console
console.log(b)

答案 19 :(得分:0)

/ *查看下面的说明* /

nums = [1,2,3,4]
var runningSum = function(nums) { 
shoppingCart =[];
runningtotal =0;  
nums.forEach(EachValue => {  
runningtotal += EachValue
shoppingCart.push(runningtotal);  
});
return shoppingCart       
};

console.log(runningSum(nums));

/ *定义一些数字* /

nums = [1,2,3,4]

/ *分配功能runningSum,一些数字* /

var runningSum = function(nums) { 
shoppingCart =[]; /* Create a empty shopping cart to store the items */
runningtotal =0;  /* Start with your beginning bill of zero items in the cart */

/ *从数字列表中删除一个数字,使用指针函数从数组中调用每个数字=> EachValue * /

nums.forEach(EachValue => {  

         (runningtotal += EachValue) 

/ *现在将值添加到运行总计以表示商品价格* /

shoppingCart.push(runningtotal);  

/ *使用push方法将其放入称为购物车的新数组* / });

返回购物车

/ *仅以1d价格输出当前购物车中的商品* /

};

    nums = [1,2,3,4]
    var runningSum = function(nums) { 
    shoppingCart =[];
    runningtotal =0;  
    nums.forEach(EachValue => {  
    runningtotal += EachValue
    shoppingCart.push(runningtotal);  
    });
    return shoppingCart       
    };

    console.log(runningSum(nums));

答案 20 :(得分:0)

var nums= [5, 10, 3, 2];
var runningSum = function(nums) {
   
    nums.reduce((acc, _, i) => (nums[i] += acc));
    return nums;
};

答案 21 :(得分:0)

我使用array.map()

提出了这个ES6版本

function prefixSum(nums) {
  let psum = 0;
  return nums.map(x => psum += x);
};

console.log(prefixSum([5, 10, 20, 30]));