Reduce over Objects
For the following data set, calculate the score
average only for available
widgets.
const widgets = [
{
score: 123,
available: false,
name: 'Widget 1'
},
{
score: 331,
available: true,
name: 'Widget 2'
},
...
]
Reduce with an object as accumulator
const calculate = ({ total, length }, score) => ({ total += score, length += 1 })
const init = { total: 0, length: 0 }
const { total, length } = widgets.filter(({ available }) => available)
.map(({ score }) => score)
.reduce(calculate, init)
const average = total / length;
Point-free Function Composition
const filter = predicate => arr => arr.filter(predicate);
const map = fn => arr => arr.map(fn);
const cursor = path => obj => obj[path];
const reduce = acc => init => arr => arr.reduce(acc, init);
const compose = (...fns) => arg => fns.reduceRight((arg, fn) => fn(arg), arg);
const combinator = f => g => h => arg => f(g(arg))(h(arg));
const sum = reduce((arr, elem) => arr + elem)(0);
const length = arr => arr.length;
const divide = x => y => x / y;
const calculate = compose(
combinator(divide)(sum)(length),
map(cursor('score')),
filter(cursor('available'))
);
const average = calculate(widgets);
Using Reducers
const reducers = {
filter: predicate => (acc, elem) => predicate(item) ? acc.concat([elem]) : acc,
map: fn => (acc, elem) => acc.concat([fn(elem)]),
}
const availableReducer = reducers.filter(({ available }) => available);
const scoreReducer => reducers.map(({ score }) => score);
const { total, length } = widgets.reduce(availableReducer, [])
.reduce(scoreReducer, [])
.reduce(calculate, init);
Using home-grown Transducers
const transducers = {
filter: predicate => step => (acc, elem) => predicate(item) ? step(acc, item) : acc,
map: fn => step => (acc, elem) => step(acc, fn(elem))
}
const availableTransducer = transducers.filter(({ available }) => available);
const scoreTransducer => transducers.map(({ score }) => score);
const reducer = availableTransducer(scoreTransducer(calculate));
const { total, length } = widgets.reduce(reducer, init);
Using Ramda Transducers
import { compose, filter, map, transduce } from 'ramda';
const prepare = compose(filter(({ available }) => available), map(({ score }) => score));
const { total, length } = transduce(
prepare,
calculate,
init,
widgets
)