data-collectors
Version:
A collection of composable reduction operations for arbitrary streams of values
70 lines (53 loc) • 2.65 kB
text/typescript
import { Collector, BaseCollector, Supplier, collect } from "../collector";
import { toArray } from "./toArray";
export interface Mapper<T, U> {
( value : T ) : U;
}
export class GroupingByCollector<T, K, A, D, M extends Map<K, D>> extends BaseCollector<T, Map<K, A>, Map<K, D>> {
protected mapper : Mapper<T, K>;
protected supplier : Supplier<M>;
protected collector : Collector<T, A, D>;
constructor ( mapper : Mapper<T, K>, supplier : Supplier<M>, collector : Collector<T, A, D> ) {
super();
this.mapper = mapper;
this.supplier = supplier;
this.collector = collector;
}
supply () : Map<K, A> {
return new Map<K, A>();
}
accumulate ( container : Map<K, A>, item : T ) : void {
const key = this.mapper( item );
if ( !container.get( key ) ) {
const subContainer = this.collector.supply();
container.set( key, subContainer );
this.collector.accumulate( subContainer, item );
} else {
this.collector.accumulate( container.get( key ), item );
}
}
combine ( container1 : Map<K, A>, container2 : Map<K, A> ) : Map<K, A> {
for ( let [ key, value ] of container2 ) {
container1.set( key, this.collector.combine( container1.get( key ), value ) );
}
return container1;
}
finish ( container : Map<K, A> ) : Map<K, D> {
let finished = this.supplier();
for ( let [ key, value ] of container ) {
finished.set( key, this.collector.finish( value ) );
}
return finished;
}
}
export function groupingBy<T, K> ( mapper : ( item : T ) => K ) : Collector<T, Map<K, T[]>, Map<K, T[]>>;
export function groupingBy<T, K, A, D> ( mapper : ( item : T ) => K, collector : Collector<T, A, D> ) : Collector<T, Map<K, A>, Map<K, D>>;
export function groupingBy<T, K, A, D, M extends Map<K, D>> ( mapper : ( item : T ) => K, supplier : Supplier<M>, collector : Collector<T, A, D> ) : Collector<T, Map<K, A>, Map<K, D>>;
export function groupingBy<T, K, A, D, M extends Map<K, D>> ( mapper : ( item : T ) => K, supplier ?: Supplier<M> | Collector<T, A, D>, collector ?: Collector<T, A, D> ) : Collector<T, any, any> {
if ( !supplier && !collector ) {
return groupingBy( mapper, () => new Map(), toArray() );
} else if ( !collector ) {
return groupingBy( mapper, () => new Map(), supplier as Collector<T, A, D> );
}
return new GroupingByCollector( mapper, supplier as Supplier<M>, collector );
}