UNPKG

@rimbu/stream

Version:

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

352 lines 17.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Transformer = void 0; var tslib_1 = require("tslib"); var common_1 = require("@rimbu/common"); var stream_1 = require("@rimbu/stream"); var Transformer; (function (Transformer) { /** * Returns a transformer that produces windows/collections of `windowSize` size, each * window starting `skipAmount` of elements after the previous, and optionally collected * by a custom reducer. * @typeparam T - the input element type * @typeparam R - the window type * @param windowSize - the amount of elements for each window * @param options - (optional) object specifying the following properties<br/> * - skipAmount - (default: `windowSize`) the amount of elements between the start of each window * - collector - (default: Reducer.toArray()) the reducer to use to convert elements to windows * @example * ```ts * Stream.of(1, 2, 3, 4, 5, 6) * .transform(Transformer.window(3)) * .toArray() * // => [[1, 2, 3], [4, 5, 6]] * ``` */ Transformer.window = function (windowSize, options) { if (options === void 0) { options = {}; } var _a = options.skipAmount, skipAmount = _a === void 0 ? windowSize : _a, _b = options.collector, collector = _b === void 0 ? stream_1.Reducer.toArray() : _b; return stream_1.Reducer.create(function () { return new Set(); }, function (state, elem, index) { var e_1, _a; try { for (var state_1 = tslib_1.__values(state), state_1_1 = state_1.next(); !state_1_1.done; state_1_1 = state_1.next()) { var instance = state_1_1.value; if (instance.index >= windowSize || instance.halted) { state.delete(instance); } else { instance.next(elem); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (state_1_1 && !state_1_1.done && (_a = state_1.return)) _a.call(state_1); } finally { if (e_1) throw e_1.error; } } if (index % skipAmount === 0) { var newInstance = collector.compile(); newInstance.next(elem); state.add(newInstance); } return state; }, function (state, _, halted) { if (halted) { return stream_1.Stream.empty(); } return stream_1.Stream.from(state).collect(function (instance, _, skip) { return instance.index === windowSize ? instance.getOutput() : skip; }); }); }; /** * Returns a transformer that returns only those elements from the input that are different to previous element * according to the optionally given `eq` function. * @param options: * - eq - (default: `Eq.objectIs`) the equality testing function * - negate: (default: false) when true will negate the given predicate<br/> * @example * ```ts * Stream.of(1, 1, 2, 3, 2, 2) * .transform(Transformer.distinctPrevious()) * .toArray() * // => [1, 2, 3, 2] * ``` */ function distinctPrevious(options) { if (options === void 0) { options = {}; } var _a = options.eq, eq = _a === void 0 ? common_1.Eq.objectIs : _a, _b = options.negate, negate = _b === void 0 ? false : _b; var token = Symbol(); return stream_1.Reducer.create(function () { return token; }, function (state, next) { return token === state || eq(state, next) === negate ? next : token; }, function (state, _, halted) { return halted || token === state ? stream_1.Stream.empty() : stream_1.Stream.of(state); }); } Transformer.distinctPrevious = distinctPrevious; /** * Returns a transformer that applies the given flatMap function to each element of the input stream, * and concatenates all the resulting resulting streams into one stream. * @typeparam T - the input element type * @typeparam T2 - the output element type * @param flatMapFun - a function that maps each input element to an `StreamSource` or a promise * resolving to a `StreamSource`. The function receives three parameters:<br/> * - `value`: the current element being processed<br/> * - `index`: the index of the current element in the input stream<br/> * - `halt`: a function that can be called to halt further processing of the input stream<br/> */ function flatMap(flatMapFun) { return stream_1.Reducer.createOutput(function () { return stream_1.Stream.empty(); }, function (state, next, index, halt) { return flatMapFun(next, index, halt); }, function (state, _, halted) { return (halted ? stream_1.Stream.empty() : state); }); } Transformer.flatMap = flatMap; /** * Returns a transformer that applies the given flatMap function to each element of the input stream, * and concatenates all the resulting resulting streams into one stream, where each resulting element is tupled * with the originating input element. * @typeparam T - the input element type * @typeparam T2 - the output element type * @param flatMapFun - a function that maps each input element to an `StreamSource` or a promise * resolving to an `StreamSource`. The function receives three parameters:<br/> * - `value`: the current element being processed<br/> * - `index`: the index of the current element in the input stream<br/> * - `halt`: a function that can be called to halt further processing of the input stream<br/> */ function flatZip(flatMapFun) { return flatMap(function (value, index, halt) { return stream_1.Stream.from(flatMapFun(value, index, halt)).mapPure(function (stream) { return [ value, stream, ]; }); }); } Transformer.flatZip = flatZip; /** * Returns a transformer that filters elements from the input stream based on the provided predicate function. * @typeparam T - the type of elements in the input stream * @param pred - a predicate function that determines whether an element should be included in the output stream, receiving:<br/> * - `value`: the current element being processed<br/> * - `index`: the index of the current element in the input stream<br/> * - `halt`: a function that can be called to halt further processing of the input stream * @param options - (optional) object specifying the following properties:<br/> * - negate: (default: false) if true, the predicate will be negated * @note if the predicate is a type guard, the return type is automatically inferred */ Transformer.filter = function (pred, options) { if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a; return flatMap(function (value, index, halt) { return pred(value, index, halt) !== negate ? stream_1.Stream.of(value) : stream_1.Stream.empty(); }); }; /** * Returns a `Transformer` instance that converts or filters its input values using given `collectFun` before passing them to the reducer. * @param collectFun - a function receiving the following arguments, and returns a new value or `skip` if the value should be skipped:<br/> * - `value`: the next value<br/> * - `index`: the value index<br/> * - `skip`: a token that, when returned, will not add a value to the resulting collection<br/> * - `halt`: a function that, when called, ensures no next elements are passed * @typeparam T - the input element type * @typeparam R - the result element type */ function collect(collectFun) { return flatMap(function (value, index, halt) { var result = collectFun(value, index, common_1.CollectFun.Skip, halt); return common_1.CollectFun.Skip === result ? stream_1.Stream.empty() : stream_1.Stream.of(result); }); } Transformer.collect = collect; /** * Returns a `Transfoemr` that inserts the given `sep` stream source elements between each received input element. * @param sep - the StreamSource to insert between each received element * @typeparam T - the input and output element type */ function intersperse(sep) { return flatMap(function (value, index) { return index === 0 ? stream_1.Stream.of(value) : stream_1.Stream.from(sep).append(value); }); } Transformer.intersperse = intersperse; /** * Returns a `Transformer` that outputs the index of each received element that satisfies the given predicate. * @param pred - a predicate function taking an element * @param options - (optional) object specifying the following properties<br/> * - negate: (default: false) when true will negate the given predicate * @typeparam T - the input element type */ function indicesWhere(pred, options) { if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a; return flatMap(function (value, index) { return pred(value) !== negate ? stream_1.Stream.of(index) : stream_1.Stream.empty(); }); } Transformer.indicesWhere = indicesWhere; /** * Returns a `Transformer` that outputs the index of each received element that is equal to the given `searchValue` value, * according to the `eq` equality function. * @param searchValue - the value to match input values to * @param options - (optional) object specifying the following properties<br/> * - eq - (default: `Eq.objectIs`) the equality testing function * - negate: (default: false) when true will negate the given predicate * @typeparam T - the input element type */ function indicesOf(searchValue, options) { if (options === void 0) { options = {}; } var _a = options.eq, eq = _a === void 0 ? common_1.Eq.objectIs : _a, _b = options.negate, negate = _b === void 0 ? false : _b; return flatMap(function (value, index) { return eq(value, searchValue) !== negate ? stream_1.Stream.of(index) : stream_1.Stream.empty(); }); } Transformer.indicesOf = indicesOf; /** * Returns a `Transformer` that applies the given `pred` function to each received element, and collects the received elements * into a `collector` that will be returned as output every time the predicate returns true. * @typeparam T - the input element type * @typeparam R - the collector result type * @param pred - a predicate function taking an element * @param options - (optional) object specifying the following properties<br/> * - negate: (default: false) when true will negate the given predicate<br/> * - collector: (default: Reducer.toArray()) a Reducer that can accept multiple values and reduce them into a single value of type `R`. */ function splitWhere(pred, options) { if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a, _b = options.collector, collector = _b === void 0 ? stream_1.Reducer.toArray() : _b; return stream_1.Reducer.create(function () { return ({ collection: collector.compile(), done: false }); }, function (state, nextValue, index) { if (state.done) { state.done = false; state.collection = collector.compile(); } if (pred(nextValue, index) === negate) { state.collection.next(nextValue); } else { state.done = true; } return state; }, function (state, _, halted) { return state.done !== halted ? stream_1.Stream.of(state.collection.getOutput()) : stream_1.Stream.empty(); }); } Transformer.splitWhere = splitWhere; /** * Returns a `Transformer` that collects the received elements * into a `collector` that will be returned as output every time the input matches the given `sepElem` value. * @typeparam T - the input element type * @typeparam R - the collector result type * @param pred - a predicate function taking an element * @param options - (optional) object specifying the following properties<br/> * - eq - (default: `Eq.objectIs`) the equality testing function * - negate: (default: false) when true will negate the given predicate<br/> * - collector: (default: Reducer.toArray()) an AsyncReducer that can accept multiple values and reduce them into a single value of type `R`. */ function splitOn(sepElem, options) { if (options === void 0) { options = {}; } var _a = options.eq, eq = _a === void 0 ? common_1.Eq.objectIs : _a, _b = options.negate, negate = _b === void 0 ? false : _b, _c = options.collector, collector = _c === void 0 ? stream_1.Reducer.toArray() : _c; return stream_1.Reducer.create(function () { return ({ collection: collector.compile(), done: false }); }, function (state, nextValue) { if (state.done) { state.done = false; state.collection = collector.compile(); } if (eq(nextValue, sepElem) === negate) { state.collection.next(nextValue); } else { state.done = true; } return state; }, function (state, _, halted) { return state.done !== halted ? stream_1.Stream.of(state.collection.getOutput()) : stream_1.Stream.empty(); }); } Transformer.splitOn = splitOn; /** * Returns a `Transformer` that collects the received elements * into a `collector` that will be returned as output every time the input matches the given `sepSlice` sequence of elements. * @typeparam T - the input element type * @typeparam R - the collector result type * @param pred - a predicate function taking an element * @param options - (optional) object specifying the following properties<br/> * - eq - (default: `Eq.objectIs`) the equality testing function * - collector: (default: Reducer.toArray()) an AsyncReducer that can accept multiple values and reduce them into a single value of type `R`. */ function splitOnSlice(sepSlice, options) { if (options === void 0) { options = {}; } var _a = options.eq, eq = _a === void 0 ? common_1.Eq.objectIs : _a, _b = options.collector, collector = _b === void 0 ? stream_1.Reducer.toArray() : _b; return stream_1.Reducer.create(function () { return ({ done: false, instances: new Map(), buffer: [], result: collector.compile(), }); }, function (state, nextValue) { var e_2, _a; if (state.done) { state.result = collector.compile(); state.done = false; } try { for (var _b = tslib_1.__values(state.instances), _c = _b.next(); !_c.done; _c = _b.next()) { var _d = tslib_1.__read(_c.value, 2), instance = _d[0], startIndex = _d[1]; instance.next(nextValue); if (instance.halted) { state.instances.delete(instance); } if (instance.getOutput()) { state.done = true; stream_1.Stream.fromArray(state.buffer, { range: { end: [startIndex, false] }, }).forEachPure(state.result.next); state.buffer = []; state.instances.clear(); return state; } } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_2) throw e_2.error; } } var nextStartsWith = stream_1.Reducer.startsWithSlice(sepSlice, { eq: eq, }).compile(); nextStartsWith.next(nextValue); if (nextStartsWith.getOutput()) { state.done = true; stream_1.Stream.fromArray(state.buffer).forEachPure(state.result.next); state.buffer = []; state.instances.clear(); return state; } else if (!nextStartsWith.halted) { state.instances.set(nextStartsWith, state.buffer.length); } if (state.instances.size === 0) { state.result.next(nextValue); } else { state.buffer.push(nextValue); } return state; }, function (state, _, halted) { if (state.done === halted) { return stream_1.Stream.empty(); } if (halted) { stream_1.Stream.fromArray(state.buffer).forEachPure(state.result.next); state.buffer = []; } return stream_1.Stream.of(state.result.getOutput()); }); } Transformer.splitOnSlice = splitOnSlice; })(Transformer || (exports.Transformer = Transformer = {})); //# sourceMappingURL=transformer.cjs.map