UNPKG

@rimbu/stream

Version:

Efficient structure representing a sequence of elements, with powerful operations for TypeScript

402 lines (399 loc) 15.6 kB
import type { Token } from '@rimbu/base'; import type { ArrayNonEmpty, IndexRange, OptLazy, StringNonEmpty, } from '@rimbu/common'; import type { Stream, StreamSource } from '@rimbu/stream'; export interface StreamConstructors { /** * Returns an empty Stream of given type T. * @typeparam T - the Stream element type * @example * ```ts * Stream.empty<number>().toArray() // => [] * ``` */ empty<T>(): Stream<T>; /** * Returns a non-empty Stream containing the given `values` * @typeparam T - the Stream element type * @param values - the values the Stream should return * @example * ```ts * Stream.of(1, 2, 3).toArray() // => [1, 2, 3] * ``` */ of<T>(...values: ArrayNonEmpty<T>): Stream.NonEmpty<T>; /** * Returns a Stream containing the values in the given `sources` concatenated * @typeparam T - the Stream element type * @param sources - a non-empty array of `StreamSource` instances containing values * @example * ```ts * Stream.from([1, 2, 3]).toArray() // => [1, 2, 3] * Stream.from('marmot').toArray() // => ['m', 'a', 'r', 'm', 'o', 't'] * Stream.from([1, 2, 3], [4, 5]).toArray() // => [1, 2, 3, 4, 5] * ``` */ from<T>( ...sources: ArrayNonEmpty<StreamSource.NonEmpty<T>> ): Stream.NonEmpty<T>; from<T>(...sources: ArrayNonEmpty<StreamSource<T>>): Stream<T>; /** * Returns a Stream returning elements from the given `array`, taking into account the given options. * @typeparam T - the Stream element type * @param array - the source of the values for the Stream * @param options - (optional) the options used to create the Stream, containing:<br/> * - range: (optional) a sub index range of the array<br/> * - reversed: (default: false) if true reverses the order of the Stream * @example * ```ts * Stream.fromArray([1, 2, 3]).toArray() // => [1, 2, 3] * Stream.fromArray([1, 2, 3], { range: { start: -2 } }).toArray() // => [1, 2] * Stream.fromArray([1, 2, 3], { range: { start: 1 }, reversed: true }).toArray() // => [3, 2] * ``` */ fromArray<T>( array: ArrayNonEmpty<T>, options?: { range?: undefined; reversed?: boolean; } ): Stream.NonEmpty<T>; fromArray<T>( array: readonly T[], options?: { range?: IndexRange | undefined; reversed?: boolean; } ): Stream<T>; /** * Returns a Stream consisting of the object keys from the given `obj` object. * @typeparam K - the object key type * @param obj - the source object * @example * ```ts * Stream.fromObjectKeys({ a: 1, b: 'b' }).toArray() // => ['a', 'b'] * ``` */ fromObjectKeys<K extends string | number | symbol>( obj: Record<K, any> ): Stream<K>; /** * Returns a Stream consisting of the object values from the given `obj` object. * @typeparam V - the object value type * @param obj - the source object * @example * ```ts * Stream.fromObjectValues({ a: 1, b: 'b' }).toArray() // => [1, 'b'] * ``` */ fromObjectValues<V>(obj: Record<any, V> | readonly V[]): Stream<V>; /** * Returns a Stream consisting of the object entries as tuples from the given `obj` object. * @typeparam K - the object key type * @typeparam V - the object value type * @param obj - the source object * @example * ```ts * Stream.fromObject({ a: 1, b: 'b' }).toArray() // => [['a', 1], ['b', 'b']] * ``` */ fromObject<K extends string | number | symbol, V>( obj: Record<K, V> ): Stream<[K, V]>; /** * Returns a Stream consisting of the characters from given string `source`, taking into account the given * options. * @typeparam S - the input string type * @param source - the source string * @param options - (optional) the options used to create the Stream, containing:<br/> * - range: (optional) a sub index range of the string<br/> * - reversed: (default: false) if true reverses the order of the Stream * @example * ```ts * Stream.fromString('marmot').toArray() // => ['m', 'a', 'r', 'm', 'o', 't'] * Stream.fromString('marmot', { range: { start: -3 } }).toArray() // => ['m', 'o', 't'] * Stream.fromString('marmot', { range: { amount: 3 }, reversed: true}).toArray() // => ['r', 'a', 'm'] * ``` */ fromString<S extends string>( source: StringNonEmpty<S>, options?: { range?: undefined; reversed?: boolean; } ): Stream.NonEmpty<string>; fromString( source: string, options?: { range?: IndexRange; reversed?: boolean; } ): Stream<string>; /** * Returns a Stream that eternally returns the given `value`. * @typeparam T - the element type * @param value - the value to return * @example * ```ts * console.log(Stream.always(5).take(4).toArray()) * => [5, 5, 5, 5] * ``` */ always<T>(value: T): Stream.NonEmpty<T>; /** * For a Stream of tuples, supplied each tuple element as an argument to given function `f` for each element of the Stream, with the optionally given `args` as extra arguments. * @typeparam T - the Stream element type, should be a tuple * @typeparam A - the optional arguments type * @param source - a Stream of tuples * @param f - the function to perform, receiving each Stream tuple element, and optionally receiving given extra `args`. * @param args - (optional) a list of extra arguments to pass to given `f` for each element * * @note used mostly for performance since a new function is not needed to spread the tuples to arguments * @example * ```ts * Stream.applyForEach([[1, 'a'], [2, 'b']], console.log, 'bongo') * // => logs: * // 1 a bongo * // 2 b bongo * ``` * @note O(N) */ applyForEach<T extends readonly unknown[], A extends readonly unknown[]>( source: StreamSource<Readonly<T>>, f: (...args: [...T, ...A]) => void, ...args: A ): void; /** * For a Stream of tuples in given `source`, returns a Stream with the result of supplying each tuple element as an argument to given `mapFun` function for each element of the Stream, * with the optionally given `args` as extra arguments. * @typeparam T - the Stream element type, should be a tuple * @typeparam A - the optional arguments type * @typeparam R - the result Stream element type * @param source - a Stream of tuples * @param mapFun - a function receiving the tuple elements as arguments, and optionally receiving given extra `args`, and returning the result Stream element. * @param args - (optional) extra arguments to pass to given `mapFun` for each element * * @note used mostly for performance since a new function is not needed to spread the tuples to arguments * @example * ```ts * const s = Stream.applyMap([[1, 'a'], [2, 'b']], List.of, true) * console.log(s.toArray()) * // => [List(1, 'a', true), List(2, 'b', true)] * ``` * @note O(N) */ applyMap<T extends readonly unknown[], A extends readonly unknown[], R>( source: StreamSource.NonEmpty<Readonly<T>>, mapFun: (...args: [...T, ...A]) => R, ...args: A ): Stream.NonEmpty<R>; applyMap<T extends readonly unknown[], A extends readonly unknown[], R>( source: StreamSource<Readonly<T>>, mapFun: (...args: [...T, ...A]) => R, ...args: A ): Stream<R>; /** * For a Stream of tuples in given `source`, returns a Stream where the result of supplying each tuple element as an argument to given `mapFun` function for each element of the Stream, * with the optionally given `args` as extra arguments, is true. * @typeparam T - the Stream element type, should be a tuple * @typeparam A - the optional arguments type * @param source - a Stream of tuples * @param options - the options used to create the Stream, containing:<br/> * - pred: a function receiving the tuple elements as arguments, and optionally receiving given extra `args`, and returning true if the element should be included in the result stream.<br/> * - negate: (default: false) if true will negate the predicate * @param args: given extra arguments to supply to the predicated if needed * @note used mostly for performance since a new function is not needed to spread the tuples to arguments * @example * ```ts * function sumEq(a: number, b: number, total: number): boolean { * return a + b === total * } * const s = Stream.applyFilter([[1, 3], [2, 4], [3, 3]], { pred: sumEq }, 6) * console.log(s.toArray()) * // => [[2, 4], [3, 3]] * ``` * @note O(N) */ applyFilter<T extends readonly unknown[], A extends readonly unknown[]>( source: StreamSource<Readonly<T>>, options: { pred: (...args: [...T, ...A]) => boolean; negate?: boolean; }, ...args: A ): Stream<T>; /** * Returns a Stream of numbers within the given `range`, increasing or decreasing with optionally given `delta`. * @param range - the range of numbers the Stream can contain * @param options - the options used to create the Stream, containing:<br/> * - delta: (default: 1) the difference between a number and the next returned number * @example * ```ts * Stream.range({ amount: 3 }).toArray() // => [0, 1, 2] * Stream.range({ start: 2, amount: 3 }).toArray() // => [2, 3, 4] * Stream.range({ start: 5 }, { delta: 2 }).toArray() // => [5, 7, 9, .... ] * ``` */ range(range: IndexRange, options?: { delta?: number }): Stream<number>; /** * Returns an infinite Stream containing random numbers between 0 and 1. * @example * ```ts * Stream.random().take(3).toArray() // => [0.3243..., 0.19524...., 0.78324...] * ``` */ random(): Stream.NonEmpty<number>; /** * Returns an infinite Stream containing random integer numbers between given `min` and `max` * @param min - the minimum value * @param max - the maximum value * @example * ```ts * Stream.randomInt(0, 10).take(3).toArray() // => [4, 9, 3] * ``` */ randomInt(min: number, max: number): Stream.NonEmpty<number>; /** * Returns a possibly infinite Stream starting with given `init` value, followed by applying given `next` function to the previous value. * @param init - an initial value * @param next - a function taking the last value, its index, and a stop token, and returning a new value or a stop token * @example * ```ts * Stream.unfold(2, v => v * v).take(4).toArray() // => [2, 4, 16, 256] * ``` */ unfold<T>( init: T, next: (current: T, index: number, stop: Token) => T | Token ): Stream.NonEmpty<T>; /** * Returns a Stream with the result of applying given `zipFun` to each successive value resulting from the given `sources`. * @param sources - the input stream sources * @param zipFun - a function taking one element from each given Stream, and returning a result value * @example * ```ts * Stream.zipWith( * [1, 2], * [3, 4, 5], * [true, false] * )( * (a, b, c) => c ? a + b : a - b * ).toArray() * // => [4, -2] * ``` * @note ends the Stream when any of the given streams ends */ zipWith<I extends readonly [unknown, ...unknown[]]>( ...sources: { [K in keyof I]: StreamSource.NonEmpty<I[K]> } & unknown[] ): <R>(zipFun: (...values: I) => R) => Stream.NonEmpty<R>; zipWith<I extends readonly [unknown, ...unknown[]]>( ...sources: { [K in keyof I]: StreamSource<I[K]> } & unknown[] ): <R>(zipFun: (...values: I) => R) => Stream<R>; /** * Returns a Stream with tuples containing each successive value from the given `sources`. * @param sources - the input stream sources * @example * ```ts * Stream.zip([1, 2, 3], [4, 5], ['a', 'b', 'c']).toArray() // => [[1, 4, 'a'], [2, 5, 'b']] * ``` * @note ends the Stream when any of the given streams ends */ zip<I extends readonly [unknown, ...unknown[]]>( ...sources: { [K in keyof I]: StreamSource.NonEmpty<I[K]> } & unknown[] ): Stream.NonEmpty<I>; zip<I extends readonly [unknown, ...unknown[]]>( ...sources: { [K in keyof I]: StreamSource<I[K]> } & unknown[] ): Stream<I>; /** * Returns a Stream with the result of applying given `zipFun` to each successive value resulting from the given `sources`, adding * given `fillValue` to any Streams that end before all streams have ended. * @param sources - the input stream sources * @param fillValue - the value to add to streams that end early * @param zipFun - a function taking one element from each given Stream, and returning a result value * @example * ```ts * Stream.zipAllWith( * [1, 2], * [3, 4, 5], * [6, 7] * )( * 0, * (a, b, c) => a + b + c, * ).toArray() * // => [10, 13, 5] * ``` */ zipAllWith<I extends readonly [unknown, ...unknown[]]>( ...sources: { [K in keyof I]: StreamSource.NonEmpty<I[K]> } & unknown[] ): <O, R>( fillValue: OptLazy<O>, zipFun: (...values: { [K in keyof I]: I[K] | O }) => R ) => Stream.NonEmpty<R>; zipAllWith<I extends readonly [unknown, ...unknown[]]>( ...sources: { [K in keyof I]: StreamSource<I[K]> } & unknown[] ): <O, R>( fillValue: OptLazy<O>, zipFun: (...values: { [K in keyof I]: I[K] | O }) => R ) => Stream<R>; /** * Returns a Stream with tuples containing each successive value from the given `sources`, adding given `fillValue` to any Streams * that end before all streams have ended. * @param fillValue - the value to add to streams that end early * @param sources - the input stream sources * @example * ```ts * Stream.zipAll( * 0, * [1, 2, 3], * [4, 5], * ['a', 'b', 'c'] * ).toArray() * // => [[1, 4, 'a'], [2, 5, 'b'], [3, 0, 'c']] * ``` */ zipAll<I extends readonly [unknown, ...unknown[]], O>( fillValue: OptLazy<O>, ...sources: { [K in keyof I]: StreamSource.NonEmpty<I[K]> } & unknown[] ): Stream.NonEmpty<{ [K in keyof I]: I[K] | O }>; zipAll<I extends readonly [unknown, ...unknown[]], O>( fillValue: OptLazy<O>, ...sources: { [K in keyof I]: StreamSource<I[K]> } & unknown[] ): Stream<{ [K in keyof I]: I[K] | O }>; /** * Returns a Stream concatenating the given `source` StreamSource containing StreamSources. * @example * ```ts * Stream.flatten(Stream.of([[1, 2], [3], [], [4]])).toArray() // => [1, 2, 3, 4] * Stream.flatten(Stream.of(['ma', 'r', '', 'mot')).toArray() // => ['m', 'a', 'r', 'm', 'o', 't'] * ``` */ flatten<T extends StreamSource.NonEmpty<S>, S>( source: StreamSource.NonEmpty<T> ): Stream.NonEmpty<S>; flatten<T extends StreamSource<S>, S>(source: StreamSource<T>): Stream<S>; /** * Returns an array containing a Stream for each tuple element in this stream. * @param options - the options used to create the result, containing:<br/> * - length: the stream element tuple length * @example * ```ts * const [a, b] = Stream.unzip(Stream.of([[1, 'a'], [2, 'b']]), 2) * a.toArray() // => [1, 2] * b.toArray() // => ['a', 'b'] * ``` */ unzip<T extends readonly unknown[] & { length: L }, L extends number>( source: Stream.NonEmpty<T>, options: { length: L; } ): { [K in keyof T]: Stream.NonEmpty<T[K]> }; unzip<T extends readonly unknown[] & { length: L }, L extends number>( source: Stream<T>, options: { length: L } ): { [K in keyof T]: Stream<T[K]> }; }