UNPKG

lilit

Version:

[![Build status][tr-svg]][travis]

681 lines 17.4 kB
import { asyncTee, asyncTeeN, forAwaitableIterator } from './common.mjs'; // OPERATORS export function map(f) { return async function* (xs) { for await (const x of xs) yield f(x); }; } export function tap(f) { return async function* (xs) { for await (const x of xs) { f(x); yield x; } }; } export const inspect = tap; export function forEach(f) { return async function (xs) { for await (const x of xs) f(x); }; } export const subscribe = forEach; export function reduce(f, init) { return async function (xs) { let res = init; for await (const x of xs) { res = f(res, x); } return res; }; } export function scan(f, init) { return async function* (xs) { let res = init; for await (const x of xs) { res = f(res, x); yield res; } }; } export const reducutions = scan; export function some(p) { return async function (xs) { for await (const x of xs) { if (p(x)) return true; } return false; }; } export function every(p) { return async function (xs) { for await (const x of xs) { if (!p(x)) return false; } return true; }; } export function filter(p) { return async function* (xs) { for await (const x of xs) { if (p(x)) yield x; } }; } export function partition(p) { return function (xs) { const [xs1, xs2] = asyncTee(xs); return [filter(p)(xs1), filter((x) => !p(x))(xs2)]; }; } export function skip(n) { return async function* (xs) { let i = 0; for await (const x of xs) { if (++i <= n) continue; yield x; } }; } export function take(n) { return async function* (xs) { let i = 0; for await (const x of xs) { if (++i > n) break; yield x; } }; } // TODO: rename? export function partitionAt(n) { return function (xs) { const [xs1, xs2] = asyncTee(xs); return [take(n)(xs1), skip(n)(xs2)]; }; } export const splitAt = partitionAt; export function skipWhile(f) { return async function* (xs) { const it = forAwaitableIterator(xs); let first; for await (const x of it) { first = x; if (!f(x)) break; } yield first; for await (const x of it) yield x; }; } export function takeWhile(f) { return async function* (xs) { for await (const x of xs) { if (f(x)) yield x; else break; } }; } export function partitionWhile(f) { return function (xs) { const [xs1, xs2] = asyncTee(xs); return [takeWhile(f)(xs1), skipWhile(f)(xs2)]; }; } export function find(p) { return async function (xs) { for await (const x of xs) { if (p(x)) return x; } return null; }; } export function findIndex(p) { return async function (xs) { let i = 0; for await (const x of xs) { if (p(x)) return i; i++; } return -1; }; } export function pluck(key) { return async function* (xs) { for await (const x of xs) yield x[key]; }; } // like pluck, but accepts an iterable of keys export function select(keys) { return async function* (xs) { for await (const x of xs) { let r = x; for (const k of keys) { r = r != null ? r[k] : undefined; } yield r; } }; } export function unzip2() { return function (xs) { const [xs1, xs2] = asyncTee(xs); return [pluck(0)(xs1), pluck(1)(xs2)]; }; } export function unzip3() { return function (xs) { const [xs1, xs2, xs3] = asyncTeeN(xs, 3); return [pluck(0)(xs1), pluck(1)(xs2), pluck(2)(xs3)]; }; } export function unzip(n = 2) { return function (xs) { const xss = asyncTeeN(xs, n); return xss.map((xs, i) => pluck(i)(xs)); }; } export function groupBy(f) { return async function (xs) { const res = new Map(); for await (const x of xs) { const key = f(x); if (!res.has(key)) res.set(key, []); res.get(key).push(x); } return res; }; } export function groupByKey(key) { return groupBy((x) => x[key]); } export function mapKeys(f) { return async function* (xs) { for await (const [k, v] of xs) yield [f(k), v]; }; } export function mapValues(f) { return async function* (xs) { for await (const [k, v] of xs) yield [k, f(v)]; }; } export function pairwise() { return async function* (xs) { const it = forAwaitableIterator(xs); let prev = (await it.next()).value; for await (const x of it) { yield [prev, x]; prev = x; } }; } export function length() { return async function (xs) { let c = 0; for await (const _ of xs) c++; return c; }; } export function min() { return async function (xs) { let res = Number.POSITIVE_INFINITY; for await (const x of xs) { if (x < res) res = x; } return res; }; } export function max() { return async function (xs) { let res = Number.NEGATIVE_INFINITY; for await (const x of xs) { if (x > res) res = x; } return res; }; } export function minMax() { return async function (xs) { let min = Number.POSITIVE_INFINITY; let max = Number.NEGATIVE_INFINITY; for await (const x of xs) { if (x < min) min = x; if (x > max) max = x; } return [min, max]; }; } export function minBy(cf) { return async function (xs) { const it = forAwaitableIterator(xs); const { done, value } = await it.next(); if (done) return null; let res = value; for await (const x of it) if (cf(x, res) < 0) res = x; return res; }; } export function maxBy(cf) { return async function (xs) { const it = forAwaitableIterator(xs); const { done, value } = await it.next(); if (done) return null; let res = value; for await (const x of it) if (cf(x, res) > 0) res = x; return res; }; } export function minMaxBy(cf) { return async function (xs) { const it = forAwaitableIterator(xs); const { done, value } = await it.next(); if (done) return [null, null]; let min = value; let max = value; for await (const x of it) { if (cf(x, min) < 0) min = x; if (cf(x, max) > 0) max = x; } return [min, max]; }; } export function minByScan(cf) { return async function* (xs) { const it = forAwaitableIterator(xs); const { done, value } = await it.next(); if (done) yield null; let res = value; for await (const x of it) { if (cf(x, res) < 0) res = x; yield res; } }; } export function maxByScan(cf) { return async function* (xs) { const it = forAwaitableIterator(xs); const { done, value } = await it.next(); if (done) yield null; let res = value; for await (const x of it) { if (cf(x, res) > 0) res = x; yield res; } }; } export function sum(zero = 0) { return async function (xs) { let res = zero; for await (const x of xs) res += x; return res; }; } export function replaceWhen(pf, ys) { return async function* (xs) { for await (const [x, y] of zip2(xs, ys)) { if (!pf(x)) yield x; else yield y; } }; } export function grouped(n, step = n) { return async function* (xs) { let group = []; for await (const x of xs) { group.push(x); if (group.length === n) { yield [...group]; for (let i = 0; i < step; i++) group.shift(); } } }; } export function startWith(...as) { return async function* (xs) { for await (const a of as) yield a; for await (const x of xs) yield x; }; } export function endWith(...zs) { return async function* (xs) { for await (const x of xs) yield x; for await (const z of zs) yield z; }; } export function sort(cf) { return async function* (xs) { let arr = []; for await (const x of xs) arr.push(x); for (const x of arr.sort(cf)) yield x; }; } export function sortScan(cf) { return async function* (xs) { let arr = []; for await (const x of xs) { arr.push(x); yield [...arr.sort(cf)]; } }; } export function flatMap(f) { return async function* (xss) { for await (const xs of xss) for await (const x of xs) yield await f(x); }; } export function distinctUntilChanged(comp = (a, b) => a === b) { return async function* (xs) { const it = forAwaitableIterator(xs); let { done, value: initial } = await it.next(); if (done) return; yield initial; for await (const x of it) if (!comp(x, initial)) yield (initial = x); }; } export function unique(comp = (a, b) => a === b) { return async function* (xs) { const arr = []; for await (const x of xs) arr.push(x); const unq = arr.filter((x, i, self) => self.findIndex(y => comp(x, y)) === i); for (const u of unq) yield u; }; } export function uniqueSorted(comp = (a, b) => a === b) { return async function* (xs) { const arr = []; for await (const x of xs) arr.push(x); arr.sort(); for await (const x of distinctUntilChanged(comp)(arr)) yield x; }; } // CONSTRUCTORS export async function* range(start = 0, end = Number.MAX_SAFE_INTEGER, step = 1) { for (let i = start; end > start ? i < end : i > end; i += step) yield i; } // TODO: rename to `entries`? export async function* enumerate(xs) { let i = 0; for await (const x of xs) yield [i++, x]; } export async function* concat(...xss) { for (const xs of xss) for await (const x of xs) yield x; } export const chain = concat; export async function* zip2(xs, ys) { const xit = forAwaitableIterator(xs); const yit = forAwaitableIterator(ys); while (true) { const [xr, yr] = await Promise.all([xit.next(), yit.next()]); if (xr.done || yr.done) break; yield [xr.value, yr.value]; } } export async function* zip3(xs, ys, zs) { const xit = forAwaitableIterator(xs); const yit = forAwaitableIterator(ys); const zit = forAwaitableIterator(zs); while (true) { const [xr, yr, zr] = await Promise.all([xit.next(), yit.next(), zit.next()]); if (xr.done || yr.done || zr.done) break; yield [xr.value, yr.value, zr.value]; } } export async function* zip(...xss) { const its = xss.map(forAwaitableIterator); while (true) { const rs = await Promise.all(its.map(it => it.next())); if (rs.some(r => r.done)) break; yield rs.map(r => r.value); } } // TODO: rename? Is this how regular zip commonly works? export async function* zipOuter(...xss) { const its = xss.map(forAwaitableIterator); while (true) { const rs = await Promise.all(its.map(it => it.next())); if (rs.every(r => r.done)) break; yield rs.map(r => r.value); } } export async function* product2(as, bs) { // if (as === bs) [as, bs] = asyncTee(as); let bs2; for await (const a of as) { [bs, bs2] = asyncTee(bs); for await (const b of bs2) { yield [a, b]; } } } export async function* product3(as, bs, cs) { // if (as === bs) [as, bs] = asyncTee(as); // if (as === cs) [as, cs] = asyncTee(as); // if (bs === cs) [bs, cs] = asyncTee(bs); let bs2; let cs2; for await (const a of as) { [bs, bs2] = asyncTee(bs); for await (const b of bs2) { [cs, cs2] = asyncTee(cs); for await (const c of cs2) { yield [a, b, c]; } } } } // TODO: generalize to n parameters export async function* product(xs, ...xss) { throw new Error('Not implemented'); } // TODO: other name (look at python itertools?) // TODO: fix implementation export async function* combinations2(xs) { let [as, bs] = asyncTee(xs); let bs2; let i = 1; for await (const a of as) { [bs, bs2] = asyncTee(bs); for await (const b of skip(i++)(bs2)) { yield [a, b]; } } } export async function* combinations3(xs) { throw Error('Not implemented'); // let [as, bs, cs] = asyncTeeN(xs, 3); // let bs2: ForOfAwaitable<X>; // let cs2: ForOfAwaitable<X>; // let i = 1; // let j = 2; // for await (const a of as) { // [bs, bs2] = asyncTee(bs); // for await (const b of skip<X>(i++)(bs2)) { // [cs, cs2] = asyncTee(cs); // for await (const c of skip<X>(j++)(cs2)) { // yield [a, b, c]; // } // } // } } export async function* combinations(xs, r = 2) { throw Error('Not implemented'); } export async function* combinationsWithReplacement2(xs) { let [as, bs] = asyncTee(xs); let bs2; let i = 0; for await (const a of as) { [bs, bs2] = asyncTee(bs); for await (const b of skip(i++)(bs2)) { yield [a, b]; } } } export async function* combinationsWithReplacement3(xs) { throw Error('Not implemented'); // let [as, bs, cs] = asyncTeeN(xs, 3); // let bs2: ForOfAwaitable<X>; // let cs2: ForOfAwaitable<X>; // let i = 0; // let j = 0; // for await (const a of as) { // [bs, bs2] = asyncTee(bs); // for await (const b of skip<X>(i++)(bs2)) { // [cs, cs2] = asyncTee(cs); // for await (const c of skip<X>(j++)(cs2)) { // yield [a, b, c]; // } // } // } } export async function* combinationsWithReplacement(xs, r = 2) { throw Error('Not implemented'); } export async function* permutations2(xs) { throw Error('Not implemented'); } export async function* permutations3(xs) { throw Error('Not implemented'); } export async function* permutations(xs, r = 2) { throw Error('Not implemented'); } export async function* constantly(value) { while (true) yield value; } export async function* cycle(xs) { let xs2; while (true) { [xs, xs2] = asyncTee(xs); for await (const x of xs2) yield x; } } export async function* repeat(xs, n) { let xs2; for (let i = 0; i < n; i++) { [xs, xs2] = asyncTee(xs); for await (const x of xs2) yield x; } } export async function* interleave2(xs, ys) { const itx = forAwaitableIterator(xs); const ity = forAwaitableIterator(ys); while (true) { const rx = await itx.next(); if (rx.done) break; else yield rx.value; const ry = await ity.next(); if (ry.done) break; else yield ry.value; } } export async function* interleave3(xs, ys, zs) { const itx = forAwaitableIterator(xs); const ity = forAwaitableIterator(ys); const itz = forAwaitableIterator(zs); while (true) { const rx = await itx.next(); if (rx.done) break; else yield rx.value; const ry = await ity.next(); if (ry.done) break; else yield ry.value; const rz = await itz.next(); if (rz.done) break; else yield rz.value; } } export async function* interleave(...xss) { const its = xss.map(forAwaitableIterator); // Throwback to the 90s outerloop: while (true) { for (const it of its) { const { done, value } = await it.next(); // Yup, this just happened if (done) break outerloop; else yield value; } } } export async function pipe(x, ...fs) { let res = await x; for (const f of fs) res = await f(res); return res; } //# sourceMappingURL=async-iter.js.map