# Moving Average in Lodash

### From OO to Clojure Workshop!

Let's write a Moving Average function in JavaScript with Lodash.

But first, we'll review the regular average function. How does that look in JavaScript without Lodash?

``````function average(numbers) {
let sum = 0;
for(let i = 0; i < numbers.length; i++)
sum += numbers[i];
return sum / (numbers.length || 1);
}
``````

The only tricky thing is that we can't divide by zero, so we are using the fact that `0` is falsey to default `numbers.length` to `1`. In that case, we'll just return 0. Not technically correct but a decent compromise.

But let's turn this into a functional style. We're iterating through a list and aggregating a result. That's a good job for `reduce`.

``````function average(numbers) {
return _.reduce(numbers, (a, b) => a + b, 0) / (numbers.length || 1);
}
``````

Very nice! Calling `reduce` with `+` and `0` could be called `sum`. Let's refactor:

``````function sum(numbers) {
return _.reduce(numbers, (a, b) => a + b, 0);
}

function average(numbers) {
return sum(numbers) / (numbers.length || 1);
}
``````

Now that's declarative! It almost reads like the English-language definition for average.

Now let's tackle the Moving Average. Given a list of numbers, you take a "window" around each number and calculate the average of the numbers in that window.

``````function moving_average(numbers) {
return _.chain(numbers)
.map(window)
.map(average)
.value();
}
``````

We can read it like this: for each `number` in `numbers`, create a window, average the window, and return the list of averages. We have the function `average` above. But what about `window`?

``````function window(_number, index, array) {
return _.slice(array, Math.max(0, index - 3), Math.min(array.length, index + 3));
}
``````

Maybe that one-liner is hard to read. We'll give the parts some names:

``````function window(_number, index, array) {
const start = Math.max(0, index - 3);
const end   = Math.min(array.length, index + 3);
return _.slice(array, start, end);
}
``````

Let's see it all together:

``````function sum(numbers) {
return _.reduce(numbers, (a, b) => a + b, 0);
}

function average(numbers) {
return sum(numbers) / (numbers.length || 1);
}

function window(_number, index, array) {
const start = Math.max(0, index - 3);
const end   = Math.min(array.length, index + 3);
return _.slice(array, start, end);
}

function moving_average(numbers) {
return _.chain(numbers)
.map(window)
.map(average)
.value();
}
``````

Okay! That works. But now I want to be able to change the window. Right now, the window is 6 elements wide. Our boss is asking if we can change it. And if we need to change it once, we probably will need to do so again in the future. Let's anticipate that and make window more flexible:

``````function make_window(before, after) {
return function (_number, index, array) {
const start = Math.max(0, index - before);
const end   = Math.min(array.length, index + after + 1);
return _.slice(array, start, end);
}
}
``````

I changed it slightly: notice that I add `index+ after + 1`, where before there was no `+ 1`. It just seems to make more sense with the names `before` and `after`.

Now how does `moving_average` look?

``````function moving_average(numbers) {
return _.chain(numbers)
.map(make_window(3, 2))
.map(average)
.value();
}
``````

Or we can pass the arguments in:

``````function moving_average(before, after, numbers) {
return _.chain(numbers)
.map(make_window(before, after))
.map(average)
.value();
}
``````