UNPKG

itertools-ts

Version:

Extended itertools port for TypeScript and JavaScript. Provides a huge set of functions for working with iterable collections (including async ones)

503 lines 16.6 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; import { toAsyncIterable, toIterable } from "./transform"; import { LengthError } from "./exceptions"; import { isString } from "./summary"; import { NoValueMonad } from "./tools"; import { map, mapAsync } from "./single"; /** * Reduces iterable source like `array.reduce()` function. * * @param data * @param reducer * @param initialValue */ export function toValue(data, reducer, initialValue) { let carry = initialValue; for (const datum of toIterable(data)) { carry = reducer(carry, datum); } return carry; } /** * Reduces async iterable source like `array.reduce()` function. * * @param data * @param reducer * @param initialValue */ export function toValueAsync(data, reducer, initialValue) { return __awaiter(this, void 0, void 0, function* () { var _a, e_1, _b, _c; let carry = initialValue; try { for (var _d = true, _e = __asyncValues(toAsyncIterable(data)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; const datum = _c; carry = yield reducer(carry, datum); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_d && !_a && (_b = _e.return)) yield _b.call(_e); } finally { if (e_1) throw e_1.error; } } return carry; }); } /** * Reduces given collection to the mean average of its items. * * Returns `undefined` if given collection is empty. * * @param data */ export function toAverage(data) { const [count, sum] = toValue(data, (carry, datum) => { const [count, sum] = carry; return [count + 1, sum + Number(datum)]; }, [0, 0]); return count ? sum / count : undefined; } /** * Reduces given async collection to the mean average of its items. * * Returns `undefined` if given collection is empty. * * @param data */ export function toAverageAsync(data) { return __awaiter(this, void 0, void 0, function* () { const [count, sum] = (yield toValueAsync(data, (carry, datum) => { const [count, sum] = carry; return [count + 1, sum + Number(datum)]; }, [0, 0])); return count ? sum / count : undefined; }); } /** * Reduces given iterable to its max value. * * Optional callable param `compareBy` must return comparable value. * If `compareBy` is not provided then items of given collection must be comparable. * * Returns `undefined` if given collection is empty. * * @param data * @param compareBy */ export function toMax(data, compareBy) { if (compareBy !== undefined) { return toValue(data, (carry, datum) => compareBy(datum) > compareBy(carry !== null && carry !== void 0 ? carry : datum) ? datum : carry !== null && carry !== void 0 ? carry : datum); } return toValue(data, (carry, datum) => { const lhs = carry !== null && carry !== void 0 ? carry : datum; const rhs = datum; return lhs >= rhs ? lhs : rhs; }); } /** * Reduces given async iterable to its max value. * * Optional callable param `compareBy` must return comparable value. * If `compareBy` is not provided then items of given collection must be comparable. * * Returns `undefined` if given collection is empty. * * @param data * @param compareBy */ export function toMaxAsync(data, compareBy) { return __awaiter(this, void 0, void 0, function* () { if (compareBy !== undefined) { return yield toValueAsync(data, (carry, datum) => __awaiter(this, void 0, void 0, function* () { return (yield compareBy(datum)) > (yield compareBy(carry !== null && carry !== void 0 ? carry : datum)) ? datum : carry !== null && carry !== void 0 ? carry : datum; })); } return yield toValueAsync(data, (carry, datum) => { const lhs = carry !== null && carry !== void 0 ? carry : datum; const rhs = datum; return lhs >= rhs ? lhs : rhs; }); }); } /** * Reduces given iterable to its min value. * * Optional callable param `compareBy` must return comparable value. * If `compareBy` is not provided then items of given collection must be comparable. * * Returns `undefined` if given collection is empty. * * @param data * @param compareBy */ export function toMin(data, compareBy) { if (compareBy !== undefined) { return toValue(data, (carry, datum) => compareBy(datum) < compareBy(carry !== null && carry !== void 0 ? carry : datum) ? datum : carry !== null && carry !== void 0 ? carry : datum); } return toValue(data, (carry, datum) => { const lhs = carry !== null && carry !== void 0 ? carry : datum; const rhs = datum; return lhs <= rhs ? lhs : rhs; }); } /** * Reduces given async iterable to its min value. * * Optional callable param `compareBy` must return comparable value. * If `compareBy` is not provided then items of given collection must be comparable. * * Returns `undefined` if given collection is empty. * * @param data * @param compareBy */ export function toMinAsync(data, compareBy) { return __awaiter(this, void 0, void 0, function* () { if (compareBy !== undefined) { return yield toValueAsync(data, (carry, datum) => __awaiter(this, void 0, void 0, function* () { return (yield compareBy(datum)) < (yield compareBy(carry !== null && carry !== void 0 ? carry : datum)) ? datum : carry !== null && carry !== void 0 ? carry : datum; })); } return yield toValueAsync(data, (carry, datum) => { const lhs = carry !== null && carry !== void 0 ? carry : datum; const rhs = datum; return lhs <= rhs ? lhs : rhs; }); }); } /** * Reduces given collection to array of its upper and lower bounds. * * Callable param `compareBy` must return comparable value. * * If `compareBy` is not proposed then items of given collection must be comparable. * * Returns `[undefined, undefined]` if given collection is empty. * * @param data * @param compareBy */ export function toMinMax(data, compareBy) { const comparableGetter = compareBy !== undefined ? compareBy : (item) => item; return toValue(data, (carry, datum) => { var _a, _b, _c, _d; carry = carry; return [ comparableGetter(datum) <= comparableGetter((_a = carry[0]) !== null && _a !== void 0 ? _a : datum) ? datum : (_b = carry[0]) !== null && _b !== void 0 ? _b : datum, comparableGetter(datum) >= comparableGetter((_c = carry[1]) !== null && _c !== void 0 ? _c : datum) ? datum : (_d = carry[1]) !== null && _d !== void 0 ? _d : datum, ]; }, [undefined, undefined]); } /** * Reduces given async collection to array of its upper and lower bounds. * * Callable param `compareBy` must return comparable value. * * If `compareBy` is not proposed then items of given collection must be comparable. * * Returns `[undefined, undefined]` if given collection is empty. * * @param data * @param compareBy */ export function toMinMaxAsync(data, compareBy) { return __awaiter(this, void 0, void 0, function* () { const comparableGetter = compareBy !== undefined ? compareBy : (item) => item; return (yield toValueAsync(data, (carry, datum) => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d; carry = carry; return [ (yield comparableGetter(datum)) <= (yield comparableGetter((_a = carry[0]) !== null && _a !== void 0 ? _a : datum)) ? datum : (_b = carry[0]) !== null && _b !== void 0 ? _b : datum, (yield comparableGetter(datum)) >= (yield comparableGetter((_c = carry[1]) !== null && _c !== void 0 ? _c : datum)) ? datum : (_d = carry[1]) !== null && _d !== void 0 ? _d : datum, ]; }), [undefined, undefined])); }); } /** * Reduces given collection to its range. * * Returns 0 if given collection is empty. * * @param numbers */ export function toRange(numbers) { const [min, max] = toMinMax(map(numbers, (n) => Number(n))); return (max !== null && max !== void 0 ? max : 0) - (min !== null && min !== void 0 ? min : 0); } /** * Reduces given async collection to its range. * * Returns 0 if given async collection is empty. * * @param numbers */ export function toRangeAsync(numbers) { return __awaiter(this, void 0, void 0, function* () { const [min, max] = yield toMinMaxAsync(mapAsync(numbers, (n) => Number(n))); return (max !== null && max !== void 0 ? max : 0) - (min !== null && min !== void 0 ? min : 0); }); } /** * Reduces given collection to the sum of its items. * * @param data */ export function toSum(data) { return toValue(data, (carry, datum) => carry + Number(datum), 0); } /** * Reduces given async collection to the sum of its items. * * @param data */ export function toSumAsync(data) { return __awaiter(this, void 0, void 0, function* () { return (yield toValueAsync(data, (carry, datum) => carry + Number(datum), 0)); }); } /** * Reduces given collection to the product of its items. * * Returns `undefined` if given collection is empty. * * @param data */ export function toProduct(data) { return toValue(data, (carry, datum) => (carry !== null && carry !== void 0 ? carry : 1) * datum); } /** * Reduces given async collection to the product of its items. * * Returns `undefined` if given collection is empty. * * @param data */ export function toProductAsync(data) { return __awaiter(this, void 0, void 0, function* () { return yield toValueAsync(data, (carry, datum) => (carry !== null && carry !== void 0 ? carry : 1) * datum); }); } /** * Reduces given iterable to its length. * * @param data */ export function toCount(data) { switch (true) { case data instanceof Array: return data.length; case isString(data): return data.length; case data instanceof Set: return data.size; case data instanceof Map: return data.size; } return toValue(data, (carry) => carry + 1, 0); } /** * Reduces given async iterable to its length. * * @param data */ export function toCountAsync(data) { return __awaiter(this, void 0, void 0, function* () { switch (true) { case data instanceof Array: case isString(data): case data instanceof Set: case data instanceof Map: return toCount(data); } return (yield toValueAsync(data, (carry) => carry + 1, 0)); }); } /** * Reduces given collection to its first value. * * @param data * * @throws LengthError if given collection is empty. */ export function toFirst(data) { for (const datum of toIterable(data)) { return datum; } throw new LengthError("Collection is empty"); } /** * Reduces given async collection to its first value. * * @param data * * @throws LengthError if given collection is empty. */ export function toFirstAsync(data) { return __awaiter(this, void 0, void 0, function* () { var _a, e_2, _b, _c; try { for (var _d = true, _e = __asyncValues(toAsyncIterable(data)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; const datum = _c; return datum; } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (!_d && !_a && (_b = _e.return)) yield _b.call(_e); } finally { if (e_2) throw e_2.error; } } throw new LengthError("Collection is empty"); }); } /** * Reduces given collection to its last value. * * @param data * * @throws LengthError if given collection is empty. */ export function toLast(data) { let isEmpty = true; let result; for (const datum of toIterable(data)) { result = datum; isEmpty = false; } if (isEmpty) { throw new LengthError("Collection is empty"); } return result; } /** * Reduces given async collection to its last value. * * @param data * * @throws LengthError if given collection is empty. */ export function toLastAsync(data) { return __awaiter(this, void 0, void 0, function* () { var _a, e_3, _b, _c; let isEmpty = true; let result; try { for (var _d = true, _e = __asyncValues(toAsyncIterable(data)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; const datum = _c; result = datum; isEmpty = false; } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (!_d && !_a && (_b = _e.return)) yield _b.call(_e); } finally { if (e_3) throw e_3.error; } } if (isEmpty) { throw new LengthError("Collection is empty"); } return result; }); } /** * Reduces given collection to its first and last values. * * @param data * * @throws LengthError if given collection is empty. */ export function toFirstAndLast(data) { let first = NoValueMonad; let last = NoValueMonad; for (const value of toIterable(data)) { if (first === NoValueMonad) { first = value; } last = value; } if (first === NoValueMonad) { throw new LengthError("Collection is empty"); } return [first, last]; } /** * Reduces given async collection to its first and last values. * * @param data * * @throws LengthError if given collection is empty. */ export function toFirstAndLastAsync(data) { return __awaiter(this, void 0, void 0, function* () { var _a, e_4, _b, _c; let first = NoValueMonad; let last = NoValueMonad; try { for (var _d = true, _e = __asyncValues(toAsyncIterable(data)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; const value = _c; if (first === NoValueMonad) { first = value; } last = value; } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (!_d && !_a && (_b = _e.return)) yield _b.call(_e); } finally { if (e_4) throw e_4.error; } } if (first === NoValueMonad) { throw new LengthError("Collection is empty"); } return [first, last]; }); } //# sourceMappingURL=reduce.js.map