-
Notifications
You must be signed in to change notification settings - Fork 5
Aggregates
Vitaly Tomilov edited this page Nov 25, 2021
·
64 revisions
Def. Aggregate (in this library)
- verb /ˈaɡrɪɡeɪt/ - with reference to operator aggregate that does the aggregation
- noun /ˈaɡrɪɡət/ - a function that operates on accumulated values, and passed into aggregate
Operator aggregate accumulates all values, then calls the aggregate function, and emits the returned value:
const i = pipe(
iterable,
...,
aggregate(values => {
// process list of values, and return the result;
return 123;
})
);
const result = [...i]; //=> [123]
// a single value with the result will be emitted,
// which means you can use i.first in place of [...i]
When your aggregate returns an iterable, and you want values emitted, follow it up with the spread operator:
const i = pipe(
iterable,
...,
aggregate(values => {
// process list of values;
return [1, 2, 3]; // return an iterable
}),
spread() // emits values from iterables
);
const result = [...i]; //=> [1, 2, 3]
There can be any number of aggregate-logic functions, from generic (sort
, group
, etc.), to specific ones.
What they all have in common is:
- They all operate on a complete dataset, which puts them out of scope, as far as iterables go.
- Implementing them as a custom operator wouldn't make sense, for the same reason as above.
That's why we have aggregate operator, so you can add any external aggregate function to the iterable pipeline with ease.
For the example below, we have:
-
input
- list of objects to be processed -
groupBy
- some external, aggregate-like function
const input = [
{group: 'first', value: 111},
{group: 'second', value: 222},
{group: 'second', value: 222},
{group: 'first', value: 333},
{group: 'first', value: 333},
{group: 'second', value: 444}
];
// groups objects by property value:
function groupBy<T>(array: T[], predicate: (v: T) => string) {
return array.reduce((acc, value) => {
(acc[predicate(value)] ||= []).push(value);
return acc;
}, {} as { [key: string]: T[] });
}
Let's select objects with unique value
, and then group those by group
value:
import {pipe, aggregate, distinct} from 'iter-ops';
const i = pipe(
input,
distinct(a => a.value), // get objects with unique "value"
aggregate(values => groupBy(values, a => a.group)) // grouping by "group" value
);
console.log(i.first);
output:
{
first: [ { group: 'first', value: 111 }, { group: 'first', value: 333 } ],
second: [ { group: 'second', value: 222 }, { group: 'second', value: 444 } ]
}
In the same manner, you can add any other external aggregate function to the iteration pipeline.