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
JavaScript
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