Ответ 1
Javascript 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]
Это пример того, что мне нужно сделать:
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
Это имеет смысл? Это возможно? Как мне это сделать?
Javascript 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]
Альтернативный подход 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;
}, []);
Элегантное решение, скопированное с Нины Шольц, с использованием карри для доступа к предыдущему значению.
const cumulativeSum = (sum => value => sum += value)(0);
console.log([5, 10, 3, 2].map(cumulativeSum));
Еще несколько вариантов с расширением массива 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]
Простое решение с использованием 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);
Как насчет это решение
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: Вы также можете использовать исходный массив. Я просто скопировал его, если мы не хотим его загрязнять.
Более общее (и эффективное) решение:
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 })
используйте сокращение, чтобы построить результат напрямую и без разрушения.
a.reduce(function(r,c,i){ r.push((r[i-1] || 0) + c); return r }, [] );
Простое решение, использующее для цикла
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)
Еще одно чистое однострочное решение с уменьшением и 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]
Моя первоначальная мысль 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 safe 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]))
Простая функция, использующая массив-уменьшение.
const arr = [6, 3, -2, 4, -1, 0, -5];
const prefixSum = (arr) => {
let result = [arr[0]]; // The first digit in the array don't change
arr.reduce((accumulator, current) => {
result.push(accumulator + current);
return accumulator + current; // update accumulator
});
return result;
}
/**
* 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)
})
Возвращает отсортированные объекты по ключевым и отсортированным массивам!!!
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,...}
Чтобы сохранить cumsum внутри функции до полной сборки, я предлагаю этот небольшой вариант на Matt 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_sums
и new_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, []);
С функциями стрелок (Не для ≤IE11 или Opera Mini), я бы написал следующее:
var cumsum = (sums,val) => sums.concat([ val + 1*sums.slice(-1) ]);
var some_sums = [5, 10, 3, 2].reduce(cumsum, []);
Используйте функцию стрелки вместо функции, вместо запятой вместо оператора, а currentIndex уменьшает обратный вызов.
[5, 10, 3, 2].reduce((r, a, i) => (r.push((i && r[i - 1] || 0) + a), r), []); // [ 5, 15, 18, 20 ]
На этот вопрос хорошо ответили другие, но я оставлю здесь и свое решение. Я старался быть кратким, не жертвуя ясностью.
myarray.reduce((a, e, i) => {
// a: Accumulator; e: current Element; i: current Index
return a.length > 0 ? [...a, e + a[i - 1]] : [e];
}, []);
Карта, Фильтр, Уменьшить, Найти, Некоторые и т.д. сильно недооценены.