Reputation: 75
I have an array that looks like this:
var array = [ [1,3,9],
[4,6,8],
[3,7,5],
[2,8,4] ];
I want to get the average number of each column, but for now I was just trying to sum them. This is my code:
var sum = function(arr) {
return arr.reduce(function(a, b) { return a + b; }, 0);
};
var tests = array.map(function(v, i) {
return sum(array.map(function(v) { return v[i]; }))
});
return tests;
The output turns the sum correctly, but it seems to be doing as many sums as there are rows (4 rows), instead of 3 corresponding to the columns. This is the output:
tests = [10, 24, 26, NULL]
Any idea why is this happening? How can I perform the calculation only for as many columns as there are instead of rows?
EDIT:
I'm using Nenad's answer which gives the correct result. But I need to implement it on Google Sheets's Script Editor, which doesn't seem to understand the shortened functions with "=>". I replaced the shortened pieces for the longer version, but I'm not getting the same result.
var array = [ [1,3,9],
[4,6,8],
[3,7,5],
[2,8,4] ];
var sums = array.reduce(function(r, e, i) {
e.forEach(function(a,j) { r[j] = (r[j] || 0) + a;
if (i == array.length-1) { r = r.map(function(el){ return el/array.length; }); }
});
return r;
}, [])
console.log(sums);
I don't see any difference between this and the shortened version, yet this one returns:
sums = [0.15625, 0.75, 1.34375];
Instead of:
sums = [2.5, 6, 6.5];
The sum is done correctly, but when I divide "el/array.length" or even "el/4", the result are these 3 weird numbers. I don't understand where are those coming from. Where did I go wrong?
Upvotes: 1
Views: 345
Reputation: 56
This will convert the 2d array of rows into a 2d array of columns and then maps each inner array of columns to an average. There is a little bit of boilerplate to make the inner reduce immutable you could use lodash/fp or another library to clean this up.
const array = [
[1,3,9],
[4,6,8],
[3,7,5],
[2,8,4]
];
const averageColumns = array => array.reduce((acc, row) => {
return row.reduce((accRow, col, index) => {
const cols = accRow[index] || [];
return [...accRow.slice(0, index), cols.concat(col), ...accRow.slice(index + 1)];
}, acc);
}, []).map(avg);
const avg = array => array.reduce((acc, next) => acc + next, 0) / array.length;
console.log(averageColumns(array));
Upvotes: 1
Reputation: 7911
To get the average of each column you'd first have to know the amount of columns. Then grab each column with map()
and to sum everything with reduce()
Now we have the column, the sum and then just divide by column length.
const arrayColumn = (a, n) => a.map(x => x[n]);
const arraySum = (a) => a.reduce((b,c) => b + c);
var arr = [
[1,3,9],
[4,6,8],
[3,7,5],
[2,8,4]
];
for(i=0; i<arr[0].length; i++){
console.log(arraySum((col = arrayColumn(arr, i))) / col.length);
}
Upvotes: 1
Reputation: 26191
I would do as follows;
var array = [ [1,3,9],
[4,6,8],
[3,7,5],
[2,8,4] ];
result = array.map(a => a.reduce((p,c,_,a) => p + c/a.length,0));
console.log(result);
As per the comments... Yes they are right, the right solution should be through a switch of the .map()
and .reduce()
;
var array = [ [1,3,9],
[4,6,8],
[3,7,5],
[2,8,4] ],
result = array.reduce((p,c) => p.map((n,i) => n + c[i]/array.length), Array(array[0].length).fill(0));
console.log(result);
Upvotes: 0
Reputation: 18764
You can transpose the array of arrays,
popular utility libraries (ramda for ex) have a transpose implementation,
but it's easy to implement your own:
const trans = arr => arr[0].map((_,i) => arr.map(x => x[i]))
var array = [
[1,3,9],
[4,6,8],
[3,7,5],
[2,8,4]
];
const res = trans(array)
console.log(res)
// to get the sum you can use reduce
console.log(res.map( x => x.reduce((a,b) => a + b )))
Upvotes: 0
Reputation: 301
map()
+ reduce()
solution
var array = [ [1,3,9], [4,6,8], [3,7,5], [2,8,4] ];
array.map(function(item, i, arr) {
arr[i] = item.reduce((a, b) => a + b, 0) / 2;
console.log(arr[i])
});
I'm a little fix up your code
you have mistake here return sum(array.map(function(v) { return v[i]; }))
var array = [ [1,3,9],
[4,6,8],
[3,7,5],
[2,8,4] ];
function sum(arr) {
return arr.reduce(function(a, b) { return a + b; }, 0);
};
var tests = array.map(function(v, i, arr) {
return sum(arr[i])
});
tests;
Upvotes: 0
Reputation: 122087
You can use reduce()
and forEach()
to return result.
var array = [
[1, 3, 9],
[4, 6, 8],
[3, 7, 5],
[2, 8, 4]
];
var sums = array.reduce(function(r, e, i) {
e.forEach((a, j) => r[j] = (r[j] || 0) + a)
return r;
}, [])
console.log(sums)
To calculate avg for each column you can add map()
on last iteration of array.
var array = [
[1, 3, 9],
[4, 6, 8],
[3, 7, 5],
[2, 8, 4]
];
var sums = array.reduce(function(r, e, i) {
e.forEach((a, j) => r[j] = (r[j] || 0) + a)
if (i == array.length - 1) r = r.map(el => el / array.length);
return r;
}, [])
console.log(sums)
Upvotes: 2