次のような配列の配列があるとしましょう。
[
[0, 1, 3],
[2, 4, 6],
[5, 5, 7],
[10, 0, 3]
]
Javascriptの内部配列の各位置にあるすべての値を合計する新しい配列を生成するにはどうすればよいですか?この場合、結果は[17、10、19]になります。内部配列の長さに関係なく機能するソリューションを用意する必要があります。これは、mapとfor-ofの組み合わせ、または場合によってはreduceを使用して可能だと思いますが、頭を完全に包むことはできません。検索しましたが、これに完全に一致する例は見つかりませんでした。
Array.prototype.reduce()
を Array.prototype.forEach()
と組み合わせて使用できます。
var array = [
[0, 1, 3],
[2, 4, 6],
[5, 5, 7],
[10, 0, 3]
],
result = array.reduce(function (r, a) {
a.forEach(function (b, i) {
r[i] = (r[i] || 0) + b;
});
return r;
}, []);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
更新、配列を減らすためのマップを取ることによるより短いアプローチ。
var array = [[0, 1, 3], [2, 4, 6], [5, 5, 7], [10, 0, 3]],
result = array.reduce((r, a) => a.map((b, i) => (r[i] || 0) + b), []);
console.log(result);
使用 Lodash 4 :
_function sum_columns(data) {
return _.map(_.unzip(data), _.sum);
}
var result = sum_columns([
[1, 2],
[4, 8, 16],
[32]
]);
console.log(JSON.stringify(result));
_
_<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
_
Lodash 4は__.unzipWith
_の動作方法を変更し、iterateeはすべての値をspread引数として一度に取得するため、レデューサースタイル__.add
_を使用できなくなりました。 Lodash の場合、次の例は問題なく機能します。
_function sum_columns(data) {
return _.unzipWith(data, _.add);
}
var result = sum_columns([
[1, 2],
[4, 8, 16],
[32],
]);
console.log(JSON.stringify(result));
_
_<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
_
__.unzipWith
_は、行が他の行より短い場所にundefined
sを挿入し、__.sum
_は未定義の値を0として扱います。(Lodash3以降)
入力データにundefined
およびnull
アイテムを含めることができ、それらを0として扱いたい場合は、次を使用できます。
_function sum_columns_safe(data) {
return _.map(_.unzip(data), _.sum);
}
function sum_columns(data) {
return _.unzipWith(data, _.add);
}
console.log(sum_columns_safe([[undefined]])); // [0]
console.log(sum_columns([[undefined]])); // [undefined]
_
_<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
_
このスニペットはLodash3で動作しますが、残念ながら、Lodash 4でundefinedを0として扱う良い方法は見つかりませんでした。現在、合計が変更されているため、_.sum([undefined]) === undefined
ES6
のワンライナー、map
およびreduce
var a = [ [0, 1, 3], [2, 4, 6], [5, 5, 7], [10, 0, 3] ];
var sum = a[0].map((_, i) => a.reduce((p, _, j) => p + a[j][i], 0));
document.write(sum);
示されているように、配列が静的であると仮定します。
a = [
[0, 1, 3],
[2, 4, 6],
[5, 5, 7],
[10, 0, 3]
]
b = []
for(i = 0; i < a[0].length; i++){
count = 0
for(j = 0; j < a.length; j++){
count += a[j][i]
}
b.Push(count)
}
console.log(b)
ネストされた配列の長さが常に同じであると仮定すると、concatとreduceを使用できます。
function totalIt (arr) {
var lng = arr[0].length;
return [].concat.apply([],arr) //flatten the array
.reduce( function(arr, val, ind){ //loop over and create a new array
var i = ind%lng; //get the column
arr[i] = (arr[i] || 0) + val; //update total for column
return arr; //return the updated array
}, []); //the new array used by reduce
}
var arr = [
[0, 1, 3],
[2, 4, 6],
[5, 5, 7],
[10, 0, 3]
];
console.log(totalIt(arr)); //[17, 10, 19]