UNPKG

geninq

Version:

A JavaScript version of the Linq library for Generators

210 lines (201 loc) 8.05 kB
import { IsFunction } from "@paulpopat/safe-type"; import { FakeHash } from "../fake-hash"; import { Build, Promised } from "./utils"; declare global { interface Generator<T = unknown, TReturn = any, TNext = unknown> { /** * Groups the elements of a sequence according to a specified key selector function. * @param builder A function to extract the key for each element. * @returns A collection of elements of the type specified where each element represents a projection over a group and its key. */ group_by< TKey extends string | number | boolean, TElement = T, TResult = [TKey, Generator<TElement>] >( builder: (item: T) => TKey ): Generator<TResult, TReturn, TNext>; /** * Groups the elements of a sequence according to a specified key selector function * and projects the elements for each group by using a specified function. * @param builder.key A function to extract the key for each element. * @param builder.element A function to map each source element to an element in an grouping. * @returns A collection of elements of the type specified where each element represents a projection over a group and its key. */ group_by< TKey extends string | number | boolean, TElement = T, TResult = [TKey, Generator<TElement>] >(builder: { key: (item: T) => TKey; element?: (item: T) => TElement; }): Generator<TResult, TReturn, TNext>; /** * Groups the elements of a sequence according to a key selector function. * The keys are compared by using a comparer and each group's elements are * projected by using a specified function. * @param builder.key A function to extract the key for each element. * @param builder.element A function to map each source element to an element in an grouping. * @param comparitor A comparitor function to compare keys with. * @returns A collection of elements of the type specified where each element represents a projection over a group and its key. */ group_by<TKey, TElement = T, TResult = [TKey, Generator<TElement>]>( builder: { key: (item: T) => TKey; element?: (item: T) => TElement; }, comparitor: (a: TKey, b: TKey) => boolean ): Generator<TResult, TReturn, TNext>; /** * Groups the elements of a sequence according to a specified key selector * function and compares the keys by using a specified comparer. * @param builder A function to extract the key for each element. * @param comparitor A comparitor function to compare keys with. * @returns A collection of elements of the type specified where each element represents a projection over a group and its key. */ group_by<TKey, TElement = T, TResult = [TKey, Generator<TElement>]>( builder: (item: T) => TKey, comparitor: (a: TKey, b: TKey) => boolean ): Generator<TResult, TReturn, TNext>; } interface AsyncGenerator<T = unknown, TReturn = any, TNext = unknown> { /** * Groups the elements of a sequence according to a specified key selector function. * @param builder A function to extract the key for each element. * @returns A collection of elements of the type specified where each element represents a projection over a group and its key. */ group_by< TKey extends string | number | boolean, TElement = T, TResult = [TKey, AsyncGenerator<TElement>] >( builder: (item: T) => Promised<TKey> ): AsyncGenerator<TResult, TReturn, TNext>; /** * Groups the elements of a sequence according to a specified key selector function * and projects the elements for each group by using a specified function. * @param builder.key A function to extract the key for each element. * @param builder.element A function to map each source element to an element in an grouping. * @returns A collection of elements of the type specified where each element represents a projection over a group and its key. */ group_by< TKey extends string | number | boolean, TElement = T, TResult = [TKey, AsyncGenerator<TElement>] >(builder: { key: (item: T) => Promised<TKey>; element?: (item: T) => Promised<TElement>; }): AsyncGenerator<TResult, TReturn, TNext>; /** * Groups the elements of a sequence according to a key selector function. * The keys are compared by using a comparer and each group's elements are * projected by using a specified function. * @param builder.key A function to extract the key for each element. * @param builder.element A function to map each source element to an element in an grouping. * @param comparitor A comparitor function to compare keys with. * @returns A collection of elements of the type specified where each element represents a projection over a group and its key. */ group_by<TKey, TElement = T, TResult = [TKey, AsyncGenerator<TElement>]>( builder: (item: T) => Promised<TKey>, comparitor: (a: TKey, b: TKey) => boolean ): AsyncGenerator<TResult, TReturn, TNext>; /** * Groups the elements of a sequence according to a specified key selector * function and compares the keys by using a specified comparer. * @param builder A function to extract the key for each element. * @param comparitor A comparitor function to compare keys with. * @returns A collection of elements of the type specified where each element represents a projection over a group and its key. */ group_by<TKey, TElement = T, TResult = [TKey, AsyncGenerator<TElement>]>( builder: { key: (item: T) => Promised<TKey>; element?: (item: T) => Promised<TElement>; }, comparitor: (a: TKey, b: TKey) => boolean ): AsyncGenerator<TResult, TReturn, TNext>; } } function CreateBuilder( builder: | ((item: unknown) => unknown) | { key: (item: unknown) => unknown; element?: (item: unknown) => unknown; } ): { key: (item: unknown) => unknown; element: (item: unknown) => unknown; }; function CreateBuilder( builder: | ((item: unknown) => Promised<unknown>) | { key: (item: unknown) => Promised<unknown>; element?: (item: unknown) => Promised<unknown>; } ): { key: (item: unknown) => Promised<unknown>; element: (item: unknown) => Promised<unknown>; }; function CreateBuilder(builder: any) { return IsFunction(builder) ? { key: builder, element: (i: any) => i, } : { key: builder.key, element: builder.element ?? ((i: any) => i), }; } Build( "group_by", function* (builder, comparitor = (a, b) => a === b) { const internal = this.array(); const b = CreateBuilder(builder); const hash = FakeHash(comparitor); for (const item of internal) { const key = b.key(item); if (hash.contains(key)) { continue; } hash.add(key); yield [ key, (function* () { for (let i = 0; i < internal.length; i++) { const item = internal[i]; const bkey = b.key(item); if (comparitor(key, bkey)) { yield b.element(item); } } })(), ]; } }, async function* (builder, comparitor = (a, b) => a === b) { const internal = await this.array(); const b = CreateBuilder(builder); const hash = FakeHash(comparitor); for (const item of internal) { const key = await Promise.resolve(b.key(item)); if (hash.contains(key)) { continue; } hash.add(key); yield [ key, (async function* () { for (let i = 0; i < internal.length; i++) { const item = internal[i]; const bkey = b.key(item); if (comparitor(key, bkey)) { yield await Promise.resolve(b.element(item)); } } })(), ]; } } );