-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1e37075
commit b7da7fd
Showing
13 changed files
with
449 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { basicAsync } from './basic-ingredients-async'; | ||
import { aggregateRecipe } from '../recipes'; | ||
|
||
export const aggregateAsync = aggregateRecipe(basicAsync); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { AnyIterable } from 'augmentative-iterable'; | ||
import { AverageStepper } from '../types'; | ||
import { getAverageStepper } from '../utils'; | ||
import { BasicIngredients } from './ingredients'; | ||
|
||
const contextSymbol = Symbol('context'); | ||
|
||
class Context { | ||
id = 0; | ||
customIds: any = {}; | ||
modMultiplyId = 0; | ||
modMultiplySymbols: any = {}; | ||
modSumId = 0; | ||
modSumSymbols: any = {}; | ||
[key: string]: any; | ||
|
||
resetIds() { | ||
this.modSumId = this.modMultiplyId = this.id = 0; | ||
} | ||
defaultId() { | ||
return (this.customIds[this.id++] ??= Symbol(this.id)); | ||
} | ||
getModMultiplyId(id: any) { | ||
return typeof id === 'symbol' | ||
? id | ||
: (this.modMultiplySymbols[id] ??= Symbol(id)); | ||
} | ||
getModSumId(id: any) { | ||
return typeof id === 'symbol' | ||
? id | ||
: (this.modSumSymbols[id] ??= Symbol(id)); | ||
} | ||
} | ||
|
||
class Aggregations { | ||
[contextSymbol] = new Context(); | ||
|
||
sum(value: number, id: string | number = this[contextSymbol].defaultId()) { | ||
const context = (this[contextSymbol].sum ??= {}); | ||
return (context[id] = (context[id] ?? 0) + value); | ||
} | ||
multiply( | ||
value: number, | ||
id: string | number = this[contextSymbol].defaultId(), | ||
) { | ||
const context = (this[contextSymbol].multiply ??= {}); | ||
return (context[id] = (context[id] ?? 1) * value); | ||
} | ||
max( | ||
value: string | number, | ||
id: string | number = this[contextSymbol].defaultId(), | ||
) { | ||
const context = (this[contextSymbol].max ??= {}); | ||
if (context[id] === undefined || context[id] < value) context[id] = value; | ||
return context[id]; | ||
} | ||
avg(value: number, id: string | number = this[contextSymbol].defaultId()) { | ||
const context = (this[contextSymbol].avg ??= {}); | ||
if (context[id] === undefined) context[id] = getAverageStepper(); | ||
const stepper: AverageStepper = context[id]; | ||
stepper.step(value); | ||
return stepper.avg; | ||
} | ||
min<T>(value: T, id: string | number = this[contextSymbol].defaultId()) { | ||
const context = (this[contextSymbol].min ??= {}); | ||
if (context[id] === undefined || context[id] > value) context[id] = value; | ||
return context[id]; | ||
} | ||
first<T>(value: T, id: string | number = this[contextSymbol].defaultId()) { | ||
const context = (this[contextSymbol].first ??= {}); | ||
if (context[id] === undefined) context[id] = { value }; | ||
return context[id].value; | ||
} | ||
last<T>(value: T) { | ||
return value; | ||
} | ||
modSum(value: number, mod: number, id = this[contextSymbol].defaultId()) { | ||
const context = (this[contextSymbol].modSumInternal ??= {}); | ||
return (context[id] = | ||
this.sum(value, this[contextSymbol].getModSumId(id)) % mod); | ||
} | ||
modMultiply( | ||
value: number, | ||
mod: number, | ||
id = this[contextSymbol].defaultId(), | ||
) { | ||
const context = (this[contextSymbol].modMultiplyInternal ??= {}); | ||
return (context[id] = | ||
this.multiply(value, this[contextSymbol].getModMultiplyId(id)) % mod); | ||
} | ||
} | ||
|
||
export function aggregateRecipe(ingredients: BasicIngredients): any { | ||
const { forEach, resolver } = ingredients; | ||
return function aggregate<T>( | ||
this: AnyIterable<T>, | ||
callback: (a: T, agg: Aggregations, prev: any) => any, | ||
result?: any, | ||
) { | ||
const agg = new Aggregations(); | ||
return resolver( | ||
forEach.call(this, (item: T) => { | ||
agg[contextSymbol].resetIds(); | ||
result = callback(item, agg, result); | ||
}), | ||
() => result, | ||
); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { basic } from './basic-ingredients'; | ||
import { aggregateRecipe } from '../recipes'; | ||
|
||
export const aggregate = aggregateRecipe(basic); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './aggregate'; | ||
export * from './all'; | ||
export * from './any'; | ||
export * from './append'; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
export interface Aggregations { | ||
sum(value: number, id?: string | number): number; | ||
multiply(value: number, id?: string | number): number; | ||
max<T extends string | number>(value: T, id?: string | number): T; | ||
avg(value: number, id?: string | number): number; | ||
min<T>(value: T, id?: string | number): T; | ||
first<T>(value: T, id?: string | number): T; | ||
last<T>(value: T, id?: string | number): T; | ||
modSum(value: number, mod: number, id?: string | number): number; | ||
modMultiply(value: number, mod: number, id?: string | number): number; | ||
} | ||
|
||
export interface AggregateFunction<T> { | ||
/** | ||
* Execute aggregations, returning the last result. This is a resolving operation | ||
* The aggregations available are: sum, multiply, max, avg, min, first, last, modSum, modMultiply | ||
* @param callback The callback to execute the aggregations. It receives a second param: an object containing all the available aggregations | ||
* @returns the last method result | ||
*/ | ||
<R, I extends R | undefined = R | undefined>( | ||
callback: (item: T, agg: Aggregations, acc: I) => R, | ||
initialize?: I, | ||
): R; | ||
} | ||
export interface AsyncAggregateFunction<T> { | ||
/** | ||
* Execute aggregations, returning the last result. This is a resolving operation | ||
* The aggregations available are: sum, multiply, max, avg, min, first, last, modSum, modMultiply | ||
* @param callback The callback to execute the aggregations. It receives a second param: an object containing all the available aggregations | ||
* @returns the last method result | ||
*/ | ||
<R, I extends R | undefined = R | undefined>( | ||
callback: (item: T, agg: Aggregations, acc: R | undefined) => R, | ||
initialize?: I, | ||
): Promise<R>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.