As an exercise in functional programming, I've decided to go through one of my projects and replace functions containing for loops with Array.prototype's higher order functions such as map and reduce.
One function in my project averages columns in a two dimensional array. It takes an arguments samples which is a 2d array of size [n][LOOKBACK]:
[
[0.6, 4.0, -0.5],
[1.0, -0.5, -0.8],
...
]
const LOOKBACK = 3
function averageChange(samples) {
let result = []
let count = 0,
i, j
for (i = 0; i < LOOKBACK; i++) {
let accumulator = 0
for (j = 0; j < samples.length; j++) {
accumulator += samples[j][i]
}
result.push(accumulator / samples.length)
}
return result
}
console.log(
averageChange([
[0.6, 4.0, -0.5],
[1.0, -0.5, -0.8]
])
)
The output should be an array of size LOOKBACK who's elements are the average of each column:
[0.8, 1.75, -0.65]
I've spent some time trying to figure out a solution to this but I can't seem to come up with one.
Is this possible using Javascript's built in Array functions?
Got an elegant solution from Kirill. If anyone else has a nice solution, I would love to see more.
Try this example with reduce and forEach functions:
let a = [
[0.6, 4.0, -0.5],
[3.0, -0.5, -0.1],
[1.0, -0.2, -0.8],
[7.0, -0.5, -0.8]
];
let b = a.reduce((acc, cur) => {
cur.forEach((e, i) => acc[i] = acc[i] ? acc[i] + e : e);
return acc;
}, []).map(e => e / a.length);
console.log(b);
Here is the more crafty method with matrix transpose:
let a = [
[0.6, 4.0, -0.5],
[3.0, -0.5, -0.1],
[1.0, -0.2, -0.8],
[7.0, -0.5, -0.8]
];
let b = a[0].map((col, i) => a.map(row => row[i]).reduce((acc, c) => acc + c, 0) / a.length);
console.log(b);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With