UNPKG

@rxjs-ninja/rxjs-array

Version:

Operators for RxJS for filtering with boolean logic

1,643 lines (1,525 loc) 52.1 kB
import { map, withLatestFrom, filter, takeWhile, tap, finalize } from 'rxjs/operators'; import { isObservable, of, Observable } from 'rxjs'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spread() { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; } /** * @packageDocumentation * @module Array */ /** * Binary searcher method * @param searchValue * @param searchArray * @param property * @private * @ignore */ function binarySearcher(searchValue, searchArray, property) { var first = 0; var last = searchArray.length - 1; var position = -1; var found = false; var middle; while (!found && first <= last) { middle = Math.round((first + last) / 2); var checkValue = typeof property === 'number' || property ? searchArray[middle][property] : searchArray[middle]; if (checkValue == searchValue) { found = true; position = middle; } else if (checkValue > searchValue) { //if in lower half last = middle - 1; } else { //in in upper half first = middle + 1; } } return position; } /** * Default sort method that provides a number value of comparison order * @private * @ignore * @param first The first comparison parameter * @param second The second comparison parameter * * @returns Number related to the sort order of two comparison parameters */ function defaultSortFn(first, second) { if (typeof first === 'string') { return first.localeCompare(second); } if (first === second) return 0; return first < second ? -1 : 1; } /** * @private * @internal * @param input */ function createOrReturnObservable(input) { return isObservable(input) ? input : of(input); } /** * Flat map `Set` into an Array of `unknown[]` * @private * @internal * @param input */ function flatMapSet(input) { return Array.isArray(input) ? __spread(input.map(function (set) { return __spread(set); })) : [__spread(input)]; } /** * Flat map `Set` into an Array of `unknown[]` * @private * @internal * @param input */ function flatMapMap(input) { return Array.isArray(input) ? __spread(input.map(function (map) { return __spread(map); })) : [__spread(input)]; } /** * Returns an Observable that emits a [[BinarySearchResult]]. It take a source Array or Set and runs a [[SortFn]] over * it, then searches it for the passed `search` value. The `BinarySearchResult` contains the index in the sorted array, * the value searched and the sorted and unsorted array. If not found the index is `-1`. * * @category Query * * @see {@link https://en.wikipedia.org/wiki/Binary_search_algorithm|Binary search algorithm} * * @typeParam T The type of the search value * @typeParam V The type of item in the Array if different to search type * * @param search The value to search for in the Array * @param property Optional property for searching tuples and objects - if an tuple use a `number` if an `Object` use a * `string` * @param sortFn Optional [[SortFn]] for sorting more complex types * * @example * Return the index of the word `bravo` in the sorted Array from a source array * ```ts * const input = ['bravo', 'delta', 'alpha', 'echo', 'charlie']; * of(input).pipe(binarySearch('bravo')).subscribe(); * ``` * Output: `<BinarySearchResult>[1, 'bravo', [...sortedArray], [...searchArray]]` * * @example * Return the index of the number `30` in the sorted Array from the source array * ```ts * const input = [100, 90, 10, 20, 40, 80, 30, 25]; * of(input).pipe(binarySearch(30)).subscribe(); * ``` * Output: `<BinarySearchResult>[3, 30, [...sortedArray], [...searchArray]]` * * @example * Return the index of the object that has `label` of `Baz`, sorted using an `index` value * ```ts * const input = [ * { index: 5, label: 'Angular' }, { index: 7, label: 'RxJS' }, * { index: 8, label: 'Ninja' }, { index: 10, label: 'TypeScript' }, * { index: 1, label: 'JavaScript' }, { index: 4, label: 'ECMAScript' }, * ]; * const sortObj = (a:, b) => { * if (a.index === b.index) return 0; * return a.index < b.index ? -1 : 1; * }; * of(input).pipe(binarySearch('Ninja', sortObj, 'label')).subscribe(); * ``` * Output: `<BinarySearchResult>[4, 'Ninja', [...sortedArray], [...searchArray]]` * * @example * Return the index of the tuple in the Array where the value at index `0` is `2`, sorted by the index `1` * ```ts * const input = [ * [1, 1], [2, 4], [3, 7], [4, 2], [5, 5], * [6, 6], [7, 3], [8, 8], [9, 10], [10, 9] * ]; * const sortArray = (a: [number, number], b: [number, number]) => { * if (a[1] === b[1]) return 0; * return a[1] < b[1] ? -1 : 1; * }; * from(input).pipe(binarySearch(2, sortArray, 0)).subscribe(); * ``` * Output: `<BinarySearchResult>[4, 2, [...sortedArray], [...searchArray]]` * * @returns An Observable that emits a [[BinarySearchResult]] */ function binarySearch(search, property, sortFn) { var search$ = createOrReturnObservable(search); var property$ = createOrReturnObservable(property); return function (source) { return source.pipe(map(function (accArray) { return [__spread(accArray), __spread(accArray).sort(sortFn || defaultSortFn)]; }), withLatestFrom(search$, property$), map(function (_a) { var _b = __read(_a, 3), _c = __read(_b[0], 2), searchArray = _c[0], sortedArray = _c[1], searchValue = _b[1], propertyValue = _b[2]; return [binarySearcher(search, sortedArray, propertyValue), searchValue, sortedArray, searchArray]; })); }; } /** * Returns an Observable that emits an Array containing unique values from the source that are not in the `compare` * parameter * * @category Filter * * @see Operator [[differenceAll]] when you want to get all differences in both source and input array * @see Operator [[filterDifference]] when you want to emit a result with duplicate values * * @typeParam T Type of value contained in the source Array or Set * * @param compare Array or Set value to compare the source value with * * @example * Returns values from the source Array not contained in the `compare` Array * ```ts * const input = ['a', 'b', 'd', 'a', 'b']; * of(input).pipe(difference(['a', 'c'])).subscribe(); * ``` * Output: `['b', 'd']` * * @returns Observable that emits an Array containing items from the source not in the comparison value */ function difference(compare) { var compare$ = createOrReturnObservable(compare); return function (source) { return source.pipe(withLatestFrom(compare$), map(function (_a) { var _b = __read(_a, 2), value = _b[0], compareValue = _b[1]; return [new Set(value), new Set(compareValue)]; }), map(function (_a) { var _b = __read(_a, 2), value = _b[0], compareValue = _b[1]; return __spread(value).filter(function (x) { return !compareValue.has(x); }); })); }; } /** * Returns an Observable that emits an tuple containing two Array both containing differences in the source and * `compare` value. The first array contains items from the source not contained in `compare` and the second values * from `compare` not in the source. * * @category Filter * * @see Operator [[difference]] for only the values from the source * @see Operator [[filterDifference]] when you want to emit a result with duplicate values * * @typeParam T Type of value contained in the source Array or Set * * @param compare Array or Set value to compare the source value with * * @example * Returns both differences between the source and array * ```ts * const input = ['a', 'b', 'd', 'a', 'b']; * of(input).pipe(differenceAll(['a', 'c', 'g'])).subscribe(); * ``` * Output: `[ ['b', 'd'], ['g'] ]` * * @returns Observable that emits an tuple containing two Array values with the source difference and input * difference */ function differenceAll(compare) { var compare$ = createOrReturnObservable(compare); return function (source) { return source.pipe(withLatestFrom(compare$), map(function (_a) { var _b = __read(_a, 2), value = _b[0], compareValue = _b[1]; return [new Set(value), new Set(compareValue)]; }), map(function (_a) { var _b = __read(_a, 2), value = _b[0], compareValue = _b[1]; return [__spread(value).filter(function (x) { return !compareValue.has(x); }), __spread(compareValue).filter(function (x) { return !value.has(x); })]; })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable that emits a boolean when all values in the source array return truthy using Array.every. * When working with data, if the array contains numbers `0` will be returned as a value to the [[PredicateFn]], but all * other falsy values will be ignored * * @category Query * * @typeParam T Type of value contained in the source Array or Set * * @param predicate Optional [[PredicateFn]] used to get a truthy value of Array values * * @example * Returns a boolean where every string item in the Array is truthy * ```ts * const input = [ ['', '', ''], ['', 'Hello', 'RxJS'], ['Hello', 'RxJS', 'Ninja'] ]; * from(input).pipe(every()).subscribe(); * ``` * Output: `false, false, true` * * @example * Returns a boolean where every string item in the Array length `< 4` * ```ts * const input = [ ['', '', ''], ['', 'Foo', 'Bar'], ['Foo', 'Bar', 'Baz'] ]; * from(input).pipe(every(v => v.length < 4)).subscribe(); * ``` * Output: `false, false, true` * * @example * Returns a boolean where every number in the array is less than `2` * ```ts * const input = [ [1, 0, 1, 0, 1, 0], [1, 0, 2, 1, 0, 2], [0, 1, 0, 1, 0, 2] ]; * from(input).pipe(every(v => v < 2)).subscribe(); * ``` * Output: `true, false, false` * * @returns An Observable that emits a boolean when all values in source array return truthy */ function every(predicate) { return function (source) { return source.pipe(map(function (value) { return __spread(value).every(function (v) { if (predicate && typeof v === 'number') { return predicate(v); } return predicate ? Boolean(v) && predicate(v) : Boolean(v); }); })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable array of values filled with Array.fill. Using the source array length, some or all the values * are replaced with the `fillWith` parameter. * * @category Modify * * @param fillWith The value to fill the array with * @param startIndex Optional start index to fill the array from * @param endIndex Optional index of the item to stop filling at, the last item filled is `fillTo - 1` * * @typeParam T Item type contained in the input Array or Set * @typeParam K Item type container in the output Array or Set * * @example * Return an array with all values replaced * ```ts * const input = ['The', 'Cake', 'is', 'a', 'lie']; * of(input).pipe(fill('CAKE!')).subscribe(); * ``` * Output: `'CAKE!', 'CAKE!', 'CAKE!', 'CAKE!', 'CAKE!'` * * @example * Return an array where all items at and after index `2` are replaced * ```ts * const input = ['The', 'Cake', 'is', 'a', 'lie']; * of(input).pipe(fill('CAKE!', 2)).subscribe(); * ``` * Output: `'The', 'Cake', 'CAKE!', 'CAKE!', 'CAKE!'` * * @example * Return an array where all items at index `2` and upto index `4` are replaced * ```ts * const input = ['The', 'Cake', 'is', 'a', 'lie']; * of(input).pipe(fill('CAKE!', 2, 4)).subscribe(); * ``` * Output: `'The', 'Cake', 'CAKE!', 'CAKE!', 'lie'` * * @returns An Observable that emits an Array of values where some or all of the source array values are replaced with * the `fillValue` */ function fill(fillWith, startIndex, endIndex) { if (startIndex === void 0) { startIndex = 0; } var fillWith$ = createOrReturnObservable(fillWith); var startIndex$ = createOrReturnObservable(startIndex); var endIndex$ = createOrReturnObservable(endIndex); return function (source) { return source.pipe(withLatestFrom(fillWith$, startIndex$, endIndex$), map(function (_a) { var _b = __read(_a, 4), value = _b[0], fillWithValue = _b[1], starIndexValue = _b[2], endIndexValue = _b[3]; return __spread(value).fill(fillWithValue, starIndexValue, endIndexValue); })); }; } /** * Returns an Observable Array containing filtered values that are not in the provided input Array or Set * * @category Filter * * @see Operator [[difference]] for only the values from the source * @see Operator [[differenceAll]] when you want to get all differences in both source and input array * * @typeParam T Type of value contained in the source Array or Set * * @param compare Array or Set value to compare the source value with * * @example * Returns the difference between the source array and the passed static array * ```ts * const input = ['a', 'b', 'd', 'a', 'b']; * of(input).pipe(filterDifference(['a', 'c'])).subscribe(); * ``` * Output: `'b', 'd', 'b'` * * @example * Returns the difference between the source array and the passed Observable array * ```ts * const input = ['a', 'b', 'd', 'a', 'b']; * of(input).pipe(filterDifference(of(['a', 'c']))).subscribe(); * ``` * Output: `'b', 'd', 'b'` * * @returns An Observable that emits an Array with the difference between source and input */ function filterDifference(compare) { var $input = createOrReturnObservable(compare); return function (source) { return source.pipe(withLatestFrom($input), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return [__spread(value), new Set(inputValue)]; }), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return value.filter(function (x) { return !inputValue.has(x); }); })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable that emits an array when all values in the source array return truthy using Array.every. * When working with data, if the array contains numbers `0` will be returned as a value to the [[PredicateFn]], but all * other falsy values will be ignored * * @category Filter * * @see The [[every]] operator returns the boolean value instead of the array * * @typeParam T Item type contained in the Array or Set * * @param predicate Optional [[PredicateFn]] used to get a truthy value of array values * * @example * Returns a array where every string item in the array is truthy * ```ts * const input = [ ['', '', ''], ['', 'Hello', 'RxJS'], ['Hello', 'RxJS', 'Ninja'] ]; * from(input).pipe(filterEvery()).subscribe(); * ``` * Output: `['Hello', 'RxJS', 'Ninja']` * * @example * Returns a array where every string item in the array length `< 4` * ```ts * const input = [ ['', '', ''], ['', 'Foo', 'Bar'], ['Foo', 'Bar', 'Baz'] ]; * from(input).pipe(filterEvery(v => v.length < 4)).subscribe(); * ``` * Output: `['Foo', 'Bar', 'Baz']` * * @example * Returns a array where every number in the array is less than `2` * ```ts * const input = [ [1, 0, 1, 0, 1, 0], [1, 0, 2, 1, 0, 2], [0, 1, 0, 1, 0, 2] ]; * from(input).pipe(filterEvery(v => v < 2)).subscribe(); * ``` * Output: `[1, 0, 1, 0, 1, 0]` * * @returns An Observable that emits a boolean when all values in source array return truthy with the [[PredicateFn]] */ function filterEvery(predicate) { return function (source) { return source.pipe(map(function (value) { return __spread(value); }), // Filter requires value to be mapped first to an array filter(function (value) { return value.every(function (v) { if (predicate && typeof v === 'number') { return predicate(v); } return predicate ? Boolean(v) && predicate(v) : Boolean(v); }); })); }; } /** * Returns an Observable Array containing filtered values that are in both the source in the provided input Array or Set * * @category Filter * * @see [[intersects]] operator for an Array of unique intersection items * * @typeParam T Item type contained in the Array or Set * * @param input Array or Set or Observable value to compare against for the intersection * * @example * Returns the intersection between the source array and the passed static array * ```ts * const input = ['a', 'b', 'd', 'a', 'b']; * of(input).pipe(filterIntersects(['a', 'd'])).subscribe(); * ``` * Output: `'a', 'd', 'a'` * * @example * Returns the intersection between the source array and the passed Observable array * ```ts * const input = ['a', 'b', 'd', 'a', 'b']; * of(input).pipe(filterIntersects(of(['a', 'd']))).subscribe(); * ``` * Output: `'a', 'd', 'a'` * * @returns An Observable that emits an Array of the intersection of input and source arrays. */ function filterIntersects(input) { var input$ = createOrReturnObservable(input); return function (source) { return source.pipe(withLatestFrom(input$), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return [__spread(value), new Set(inputValue)]; }), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return value.filter(function (x) { return inputValue.has(x); }); })); }; } /** * Returns an Observable that emits an array when one of the values in the source array return truthy using Array.some * When working with data, if the array contains numbers `0` will be returned as a value to the [[PredicateFn]], but all * other falsy values will be ignored * * @category Filter * * @see The [[some]] operator returns the boolean value instead of the array * * @typeParam T Item type contained in the Array or Set * * @param predicate Optional [[PredicateFn]] used to get a truthy value of array values * * @example * Returns a array where at least one string item in the array is truthy * ```ts * const input = [ ['', '', ''], ['', 'Hello', 'RxJS'], ['Hello', 'RxJS', 'Ninja'] ]; * from(input).pipe(filterSome()).subscribe(); * ``` * Output: `['', 'Hello', 'RxJS'], ['Hello', 'RxJS', 'Ninja']` * * @example * Returns a array where at least string item in the array length `< 4` * ```ts * const input = [ ['', '', ''], ['', 'Foo', 'Bar'], ['Foo', 'Bar', 'Baz'] ]; * from(input).pipe(filterEvery(v => v.length < 4)).subscribe(); * ``` * Output: `['', 'Foo', 'Bar'], ['Foo', 'Bar', 'Baz']` * * @example * Returns a array where at least one number in the array is less than `2` * ```ts * const input = [ [1, 0, 1, 0, 1, 0], [1, 0, 2, 1, 0, 2], [0, 1, 0, 1, 0, 2] ]; * from(input).pipe(filterSome(v => v < 2)).subscribe(); * ``` * Output: `[1, 0, 1, 0, 1, 0], [1, 0, 2, 1, 0, 2], [0, 1, 0, 1, 0, 2]` * * @returns An Observable that emits a boolean when all values in source array return truthy with the [[PredicateFn]] */ function filterSome(predicate) { return function (source) { return source.pipe(map(function (value) { return __spread(value); }), // Filter requires value to be mapped first to an array filter(function (value) { return value.some(function (v) { if (predicate && typeof v === 'number') { return predicate(v); } return predicate ? Boolean(v) && predicate(v) : Boolean(v); }); })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable value of the first truthy value found in a source array, or `undefined` using Array.find. * When working with data, if the array contains numbers `0` will be returned as a value to the [[PredicateFn]], but all * other falsy values will be ignored * * @category Filter * * @typeParam T Item type contained in the Array or Set * * @param predicate Optional [[PredicateFn]] used to get a truthy value of array values * * @example * Return the first truthy string in the array * ```ts * const input = ['', '', 'Hello', 'RxJS', 'Ninja'] * of(input).pipe(find()).subscribe(); * ``` * Output: `'Hello'` * * @example * Return the first truthy string that has a length `< 5` * ```ts * const input = ['', '', 'Hello', 'RxJS', 'Ninja']; * of(input).pipe(find(v => v.length < 5)).subscribe(); * ``` * Output: `'RxJS'` * * @returns An Observable that emits the first found value from the array, or `undefined` */ function find(predicate) { return function (source) { return source.pipe(map(function (value) { return __spread(value).find(function (v) { if (predicate && typeof v === 'number') { return predicate(v); } return predicate ? Boolean(v) && predicate(v) : Boolean(v); }); })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable array of truthy values from a source Array or Set * When working with data, if the array contains numbers `0` will be returned as a value to the [[PredicateFn]], but all * other falsy values will be ignored * * @category Filter * * @param predicate Optional [[PredicateFn]] used to get a truthy value of array values * * @example * Return an array of all numbers that are truthy * ```ts * const input = [0, 10, 1, 0, 6, 6, 0, 1]; * of(input).pipe(findAll()).subscribe(); * ``` * Output: `[10, 1, 6, 6, 1]` * * @example * Return an array of values where the source array value length `>= 5` * ```ts * const input = ['', '', 'Hello', 'RxJS', 'Ninja']; * of(input).pipe(findAll(v => v.length >= 5)).subscribe(); * ``` * Output: `['Hello', 'Ninja']` * * @returns An Observable that emits an array containing all truthy values from a source array */ function findAll(predicate) { return function (source) { return source.pipe(map(function (value) { return __spread(value).filter(function (v) { if (predicate && typeof v === 'number') { return predicate(v); } return predicate ? Boolean(v) && predicate(v) : Boolean(v); }); })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable value of the last truthy value found in a source array, or `undefined` using Array.find * When working with data, if the array contains numbers `0` will be returned as a value to the [[PredicateFn]], but all * other falsy values will be ignored * * @category Filter * * @typeParam T Item type contained in the Array or Set * * @param predicate Optional [[PredicateFn]] used to get a truthy value of array values * * @example * Return the last truthy string in the array * ```ts * const input = ['', '', 'Hello', 'RxJS', 'Ninja'] * of(input).pipe(findLast()).subscribe(); * ``` * Output: `'Ninja'` * * @example * Return the last truthy string that has a length `>= 5` * ```ts * const input = ['', '', 'Hello', 'RxJS', 'Ninja', 'Docs']; * of(input).pipe(findLast(v => v.length >= 5)).subscribe(); * ``` * Output: `'Ninja'` * * @returns An Observable that emits the last found value from the array, or `undefined` */ function findLast(predicate) { return function (source) { return source.pipe(map(function (value) { return __spread(value).reverse().find(function (v) { if (predicate && typeof v === 'number') { return predicate(v); } return predicate ? Boolean(v) && predicate(v) : Boolean(v); }); })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable number which is the index of the first value found in an array using Array.findIndex * When working with data, if the array contains numbers `0` will be returned as a value to the [[PredicateFn]], but all * other falsy values will be ignored * * @category Query * * @typeParam T Item type contained in the Array or Set * * @param predicate Optional [[PredicateFn]] used to get a truthy or falsy value of array values * * @example * Returns the index of the first value that is `> 2` * ```ts * const input = [1, 2, 3, 4, 5] * of(input).pipe(findIndex(v => v > 2)).subscribe(); * ``` * Output: `2` * * @example * Returns the index of the first string where the length `< 5` * ```ts * const input = ['Hello', 'RxJS', 'Ninja']; * of(input).pipe(findIndex(v => v.length < 5)).subscribe(); * ``` * Output: `1` * * @returns An Observable that emits a number value, the index of first value where [[PredicateFn]] is true */ function findIndex(predicate) { return function (source) { return source.pipe(map(function (value) { return __spread(value).findIndex(function (v) { if (predicate && typeof v === 'number') { return predicate(v); } return predicate ? Boolean(v) && predicate(v) : Boolean(v); }); })); }; } /** * Returns an Observable array where the source array contains boolean values, and flips the value to the opposite * boolean. * * @category Modify * * @example * Returns an array of all binary values flipped * ```ts * const input = [false, true, false]; * of(input).pipe(flipArray()).subscribe(); * ``` * Output: `[true, false, true]` * * @returns Observable array of boolean values that are flipped from their original value */ function flipArray() { return function (source) { return source.pipe(map(function (value) { return __spread(value).map(function (v) { return !v; }); })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable that emits an Array from a Map * * @category Map * * @typeParam K The type of value in the Map key * @typeParam V Type of the value in the Map value * * @param input Input to create the emit values from, can be argument list of Map, an array of Map or an Observable * or Promise source * * @example * Create Array from Map * ```ts * const input = new Map([ [1, 'a'], [2, 'b'], [3, 'c'] ]); * fromMap(input).subscribe(); * ``` * Output: `[1, 'a'], [2, 'b'], [3, 'c']` * * @returns Observable that emits an Array from the input Map */ function fromMap(input) { return new Observable(function (subscriber) { createOrReturnObservable(input).pipe(takeWhile(function () { return !subscriber.closed; }), map(function (value) { return flatMapMap(value); }), tap(function (value) { for (var i = 0; i < value.length; i++) { subscriber.next(value[i]); } }), finalize(function () { return !subscriber.closed && subscriber.complete(); })).subscribe(); /* istanbul ignore next-line */ return function () { return !subscriber.closed && subscriber.complete(); }; }); } /** * @packageDocumentation * @module Array */ /** * Returns an Observable that emits an Array from a Set * * @category Set * * @typeParam T The type of value contained in the Set * * @param input Input to create the emit values from, can be argument list of Set, an array of Set or an Observable * or Promise source * * @example * Create Array from Set * ```ts * const input = new Set(1, 1, 2, 2, 3, 3, 4, 4); * fromSet(input).subscribe(); * ``` * Output: `[1, 2, 3, 4]` * * @returns Observable that emits an Array from the input Set */ function fromSet(input) { return new Observable(function (subscriber) { createOrReturnObservable(input).pipe(takeWhile(function () { return !subscriber.closed; }), map(function (value) { return flatMapSet(value); }), tap(function (value) { for (var i = 0; i < value.length; i++) { subscriber.next(value[i]); } }), finalize(function () { return !subscriber.closed && subscriber.complete(); })).subscribe(); /* istanbul ignore next-line */ return function () { return !subscriber.closed && subscriber.complete(); }; }); } /** * @packageDocumentation * @module Array */ /** * Checks if an Iterable is only one of Array or `Set` * @private * @internal * @param input */ function isArrayOrSet(input) { if (Array.isArray(input)) { return true; } else return input instanceof Set; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable Number if the input is a single value, or Array of numbers in the input is an Array. * These are the index numbers of first truthy value in the source array using Array.indexOf * * @category Query * * @typeParam T Item type contained in the Array or Set * * @param input A value or array of values to get the index of in the source array * @param startIndex Optional index to start searching from in the array, starts from `0` * * @example * Returns the first index of the word `RxJS` in the array * ```ts * const input = [ ['RxJS', 'Ninja' ], ['Learn', 'RxJS'], ['Foo', 'Bar'] ]; * from(input).pipe(indexOf('RxJS')).subscribe(); * ``` * Output: `0, 1, -1` * * @example * Returns an array of the first index of the words `RxJS` and `Ninja` in the array * ```ts * const input = [ ['RxJS', 'Ninja' ], ['Learn', 'RxJS'], ['Foo', 'Bar'] ]; * of(input).pipe(indexOf(['RxJS', 'Ninja'])).subscribe() * ``` * Output: `[0, 1], [1, -1], [-1, -1]` * * @example * Returns the first index of the word `RxJS` in the array starting from index `1` * ```ts * const input = [ ['RxJS', 'Ninja' ], ['Learn', 'RxJS'], ['Foo', 'Bar'] ]; * of(input).pipe(indexOf('RxJS', 1)).subscribe() * ``` * Output: `-1, 1, -1` * * @returns Observable number or array of numbers containing the index of the first found value */ function indexOf(input, startIndex) { var input$ = createOrReturnObservable(input); var startIndex$ = createOrReturnObservable(startIndex); return function (source) { return source.pipe(withLatestFrom(input$, startIndex$), map(function (_a) { var _b = __read(_a, 3), _c = __read(_b[0]), value = _c.slice(0), inputValue = _b[1], startIndexValue = _b[2]; return isArrayOrSet(inputValue) ? __spread(inputValue).map(function (val) { return value.indexOf(val, startIndexValue); }) : [value.indexOf(inputValue, startIndexValue)]; })); }; } /** * Returns an Observable Array containing unique values that are in both the source and provided input Array or Set * * @category Filter * * @see [[filterIntersects]] operator for an Array containing potential duplicate intersections * * @typeParam T Item type contained in the Array or Set * * @param input Array or Set or Observable value to compare against for the intersection * * @example * Returns the intersection between the source array and the passed static array * ```ts * const input = ['a', 'b', 'd', 'a', 'b']; * of(input).pipe(intersects(['a', 'd'])).subscribe(); * ``` * Output: `'a', 'd'` * * @example * Returns the intersection between the source array and the passed Observable array * ```ts * const input = ['a', 'b', 'd', 'a', 'b']; * of(input).pipe(intersects(of(['a', 'd']))).subscribe(); * ``` * Output: `'a', 'd'` * * @returns An Observable that emits an array of the intersection of input and source arrays. */ function intersects(input) { var input$ = createOrReturnObservable(input); return function (source) { return source.pipe(withLatestFrom(input$), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return [new Set(value), new Set(inputValue)]; }), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return __spread(value).filter(function (x) { return inputValue.has(x); }); })); }; } /** * Returns an Observable that emits a boolean value if the source Observable Array or Set has equal non-duplicate * content of the input Array or Set * * @category Query * * @remarks The source set (A) is equal in content to the input set (B) (`A == B`) * * @typeParam T The input type of the source Array or Set * * @param input The Array or Set to check if the set is equal * * @example Return if the source array is a subset of the input array * ```ts * const input = [ ['a', 'b', 'c'], ['a', 'c', 'b', 'a'], ['a', 'b', 'z', 'x' ] ]; * from(input).pipe(isEqualSet(['a', 'b', 'c'])).subscribe() * ``` * Output: `true, true, false` * * @returns Observable that emits a boolean of the source array has equal content to the input array */ function isEqualSet(input) { var input$ = createOrReturnObservable(input); return function (source) { return source.pipe(withLatestFrom(input$), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return [new Set(value), new Set(inputValue)]; }), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return [value, inputValue, inputValue.size == value.size]; }), map(function (_a) { var _b = __read(_a, 3), value = _b[0], inputValue = _b[1], sameSize = _b[2]; return sameSize ? __spread(value).every(function (e) { return __spread(inputValue).includes(e); }) : false; })); }; } /** * Returns an Observable that emits a boolean value if the source Observable Array or Set is a subset of * the input Array or Set * * @category Query * * @remarks The source set (A) is subset of the input set (B) when B contains all elements of A (`A ⊆ B`) * * @typeParam T The input type of the source Array or Set * * @param input The Array or Set to check if the value is a subset of it * * @example Return if the source array is a subset of the input array * ```ts * const input = [ ['a', 'c'], b: ['a', 'e'], c: ['x', 'z'] ] * from(input).pipe(isSubsetOf(['a', 'b', 'c'])).subscribe() * ``` * Output: `true, false, false` * * @returns Observable that emits a boolean of the source array being a subset of the input array */ function isSubsetOf(input) { var input$ = createOrReturnObservable(input); return function (source) { return source.pipe(withLatestFrom(input$), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return [new Set(value), new Set(inputValue)]; }), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return __spread(value).filter(function (e) { return __spread(inputValue).includes(e); }).length === value.size; })); }; } /** * Returns an Observable that emits a boolean value if the source Observable Array or Set is a superset of * the input Array or Set * * @category Query * * @remarks The source set (A) is superset of the input set (B) when A contains all elements of B. (`A ⊇ B`) * * @typeParam T The input type of the source Array or Set * * @param input The Array or Set to check if the value is a subset of it * * @example Return if the source array is a subset of the input array * ```ts * const input = [ ['a', 'b', 'c'], b: ['a', 'b', 'e'], c: ['x', 'y', 'z'] ] * from(input).pipe(isSupersetOf(['a', 'c'])).subscribe() * ``` * Output: `true, false, false` * * @returns Observable that emits a boolean of the source array being a superset of the input array */ function isSupersetOf(input) { var input$ = createOrReturnObservable(input); return function (source) { return source.pipe(withLatestFrom(input$), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return [new Set(value), new Set(inputValue)]; }), map(function (_a) { var _b = __read(_a, 2), value = _b[0], inputValue = _b[1]; return __spread(inputValue).filter(function (e) { return __spread(value).includes(e); }).length === inputValue.size; })); }; } /** * Returns an Observable that emits a joining the values of the Array or Set using the `separator` character using * Array.join * * @category Modify * * @typeParam T Item type contained in the Array or Set * * @param separator Separator to be used to join strings. Default value is a space (` `) character. * * @example * Returns a string of an array joined with spaces * ```ts * const input = ['Hello', 'RxJS', 'Ninja']; * of(input).pipe(join()).subscribe(); * ``` * Output: `'Hello RxJS Ninja'` * * @example * Returns a string of an array joined with a comma and space * ```ts * const input = ['Name', 'Age', 'Location']; * of(input).pipe(join(', ')).subscribe(); * ``` * Output: `'Name, Age, Location'` * * @returns Observable string from the joined values in the source array */ function join(separator) { if (separator === void 0) { separator = ' '; } var separator$ = createOrReturnObservable(separator); return function (source) { return source.pipe(withLatestFrom(separator$), map(function (_a) { var _b = __read(_a, 2), value = _b[0], separatorValue = _b[1]; return __spread(value).join(separatorValue); })); }; } /** * Returns an Observable number or array of numbers. These are the index numbers of first truthy value in the source * array using Array.lastIndexOf * * @category Query * * @typeParam T The input type of the source Array or Set * * @param input A value or array of values to get the index of in the source array * @param fromIndex Optional index to start searching from in the array * * @example * Returns the last index of the word `RxJS` in the array * ```ts * const input = [ ['RxJS', 'Ninja', 'RxJS' ], ['Learn', 'RxJS'], ['Foo', 'Bar'] ]; * from(input).pipe(lastIndexOf('RxJS')).subscribe(); * ``` * Output: `2, 1, -1` * * @example * Returns an array of the last index of the words `RxJS` and `Ninja` in the array * ```ts * const input = [ ['RxJS', 'Ninja', 'RxJS' ], ['Ninja', 'Learn', 'RxJS'], ['Foo', 'Bar'] ]; * of(input).pipe(lastIndexOf(['RxJS', 'Ninja'])).subscribe() * ``` * Output: `[2, 1], [0, 2], [-1, -1]` * * @example * Returns the last index of the word `RxJS` in the array starting from index `1` * ```ts * const input = [ ['RxJS', 'Ninja', 'RxJS', 'Ninja', 'Ninja' ], ['Learn', 'RxJS'], ['Foo', 'Bar'] ]; * of(input).pipe(lastIndexOf('RxJS', 1)).subscribe() * ``` * Output: `2, 1, -1` * * @example * Returns the last index of the word `RxJS` in the array comparing with lower case * ```ts * const input = [ ['RxJS', 'Ninja', 'RxJS'], ['Learn', 'RxJS'], ['Foo', 'Bar'] ]; * of(input).pipe(lastIndexOf('rxjs', 0, v => v.toLowerCase())).subscribe() * ``` * Output: `2, 1, -1` * * @returns Observable number or array of numbers containing the index of the last found value */ function lastIndexOf(input, fromIndex) { var input$ = createOrReturnObservable(input); var fromIndex$ = createOrReturnObservable(fromIndex); return function (source) { return source.pipe(withLatestFrom(input$, fromIndex$), map(function (_a) { var _b = __read(_a, 3), _c = __read(_b[0]), value = _c.slice(0), inputValue = _b[1], fromIndexValue = _b[2]; fromIndexValue = fromIndexValue || value.length - 1; return isArrayOrSet(inputValue) ? __spread(inputValue).map(function (val) { return value.lastIndexOf(val, fromIndexValue); }) : [value.lastIndexOf(inputValue, fromIndexValue)]; })); }; } /** * Returns an Observable that emits an array from a source Map object. * * @category Map * * @typeParam K The key type of the source Map * @typeParam T The value type of the source Map * * @example Convert a Map into an Array * ```ts * const input = new Map([ [1, 'a'], [2, 'b'], [3, 'c'] ]); * of(input).pipe(mapToArray()).subscribe(); * ``` * Output: `[ [1, 'a'], [2, 'b'], [3, 'c'] ]` * * @returns Observable that emits a Array from a source Map */ function mapToArray() { return function (source) { return source.pipe(map(function (value) { return __spread(value); })); }; } /** * Returns an Observable that emits an Array from a source Object using Object.entries, the Array contains * tuples of the key as a string and the value * * @category Object * * @remarks Regardless of Object key type the result Array will have a `string` key value * * @typeParam K The key type of the source Object * @typeParam T The value type of the source Object * * @example Convert an Object into an array of entries * ```ts * const input = { 1: 'a', 2: 'b', 3: 'c' }; * of(input).pipe(objectEntriesToArray()).subscribe(); * ``` * Output: `[ ['1', 'a'], ['2', 'b'], ['3', 'c'] ]` * * @returns Observable that emits a Array from a source Object entries */ function objectEntriesToArray() { return function (source) { return source.pipe(map(function (value) { return Object.entries(value); })); }; } /** * Returns an Observable that emits an array from a source Object using Object.keys, the array contains * the object keys as strings. * * @category Object * * @remarks Regardless of Object key type the result Array will have a `string` key value * * @typeParam K The key type of the source Object * @typeParam T The value type of the source Object * * @example Convert an Object into an array of keys * ```ts * const input = { 1: 'a', 2: 'b', 3: 'c' }; * of(input).pipe(objectKeysToArray()).subscribe(); * ``` * Output: `[ '1', '2', '3' ]` * * @returns Observable that emits a Array of strings from a source Object keys */ function objectKeysToArray() { return function (source) { return source.pipe(map(function (value) { return Object.keys(value); })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable that emits array taking the source and running the result of Array.reverse * * @category Modify * * @typeParam T Item type contained in the Array or Set * * @example * Reverse an array of values * ```ts * const input = ['Hello', 'RxJS', 'Ninja']; * of(input).pipe(reverse()).subscribe(); * ``` * Output: `['Ninja', 'RxJS', 'Hello']` * * @returns Observable that emits an array which is reversed from the source array */ function reverse() { return function (source) { return source.pipe(map(function (value) { return __spread(value).reverse(); })); }; } /** * Returns an Observable that emits an Array from a source Set. * * @category Set * * @typeParam T The type of value contained in the Set * * @example Convert a Set into an Array * ```ts * const input = new Set([1, 1, 2, 3, 3, 4, 5]); * of(input).pipe(setToArray()).subscribe(); * ``` * Output: `[1, 2, 3, 4, 5]` * * @returns Observable that emits a Array from a source Set */ function setToArray() { return function (source) { return source.pipe(map(function (value) { return __spread(value); })); }; } /** * Returns an Observable that emits an array taking a source array and randomly shuffling the elements * * @category Modify * * @typeParam T Item type contained in the Array or Set * * @example * Return a randomly shuffled array * ```ts * const input = [1, 2, 3, 4, 5, 6]; * of(input).pipe(shuffle()).subscribe(); * ``` * Output: `[4, 2, 5, 1, 6, 3]` * * @returns Observable that emits an array of values shuffled from the source array */ function shuffle() { return function (source) { return source.pipe(map(function (_a) { var _b; var _c = __read(_a), arr = _c.slice(0); for (var i = arr.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); _b = __read([arr[j], arr[i]], 2), arr[i] = _b[0], arr[j] = _b[1]; } return arr; })); }; } /** * @packageDocumentation * @module Array */ /** * Returns an Observable that emits a boolean when all values in the source Array or Set return truthy using Array.some * When working with data, if the array contains numbers `0` will be returned as a value to the [[PredicateFn]], but all * other falsy values will be ignored * * @category Query * * @see The [[filterSome]] operator returns the array value instead of boolean * * @typeParam T Item type contained in the Array or Set * * @param predicate Optional [[PredicateFn]] used to get a truthy value of array values * * @example * Return a boolean value if some of the elements are truthy * ```ts * const input = [ [0, 0, 0], [0, 0, 1], [1, 1, 1] ] * from(input).pipe(some()).subscribe() * ``` * Output: `false, true, true` * * @example * Return a boolean value if some of the elements are truthy with a predicate * ```ts * const input = [ ['RxJS', 'Rocks'], ['RxJS', 'Ninja'], ['Foo', 'Bar'] ] * fromArray(input).pipe(some(v => v === 'RxJS')).subscribe() * ``` * Output: `true, true, false` * * @returns An Observable that emits a boolean when all values in source array return truthy */ function some(predicate) { return function (source) { return source.pipe(map(function (value) { return __spread(value).some(function (v) { if (predicate && typeof v === 'number') { return predicate(v); } return predicate ? Boolean(v) && predicate(v) : Boolean(v); }); })); }; } /** * Returns an Observable that emits an array of sorted values from the source Array or Set using the [[SortFn]] * * @category Modify * * @typeParam T Item type contained in the Array or Set * * @param sortFn Optional [[SortFn]] used to sort the array, if not provided the `defaultSortFn` is used. * * @example * Returns a sorted array of numbers * ```ts * const input = [2, 4, 6, 1, 3, 5]; * of(input).pipe(sort()).subscribe(); * ``` * Output: `[1, 2, 3, 4, 5, 6]` * * @example * Returns a sorted array of tuples, sorting on index `1` * ```ts * const input = [ * [10, 2], [20, 4], [30, 6], * [40, 1], [50, 3], [60, 5] * ]; * const sortTuple = (a, b) => { * if (a[1] === b[1]) return 0; * return a[1] < b[1] ? -1 : 1; * } * * of(input).pipe(sort(sortTuple)).subscribe(); * ``` * Output: `[ [40, 1], [10, 2], [50, 3], [20, 4], [60, 5], [30, 6] ]` * * @returns Observable array of values from source array sorted via [[SortFn]] */ function sort(sortFn) { return function (source) { return source.pipe(map(function (value) { return __spread(value).sort(sortFn || defaultSortFn); })); }; } /** * Returns an Observable that emits an array of sorted mapped values from a source array where values are mapped to * type `K` using a [[MapFn]]. * * @category Modify * * @typeParam T The input type of the source Array or Set * @typeParam K The type of data in the emitted array * * @param mapFn The [[MapFn]] to map the value in the array * @param sortFn Optional [[SortFn]] used to sort the array, if not provided the `defaultSortFn` is used. * * @example * Returns a sorted array of binary values, sorting by number then converting to boolean * ```ts * const input = [5, 8, 2, 7, 1, 6]; * of(input).pipe(sortMap(value => value >= 5 ? true : false)).subscribe(); * ``` * Output: `[false, false, true, true, true, true]` * * @example * Returns a sorted array of strings from an object, with [[SortFn]] and [[MapFn]] * ```ts * const sortFn = (a: any, b: any) => { * if (a.index === b.index) return 0; * return a.index < b.index ? -1 : 0 * } * * const mapFn = (item: any): string => item.label; * * const input = [ * { index: 5, label: 'Moo' }, { index:8, label: 'Baz' }, * { index: 2, label: 'Bar' }, { index: 7: label: 'Buzz' }, * { index: 1, label: 'Foo' } , { index: 6,