From d94df5786dddf6ef6915af79c3fbf0331ddfd2bd Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 15 Nov 2019 17:04:07 +0000 Subject: [PATCH] feat(arrays): add arraySeq(), arrayIterator() & tests --- packages/arrays/src/index.ts | 2 ++ packages/arrays/src/iterator.ts | 28 ++++++++++++++++++++++++++++ packages/arrays/src/seq.ts | 30 ++++++++++++++++++++++++++++++ packages/arrays/test/iterator.ts | 13 +++++++++++++ packages/arrays/test/seq.ts | 21 +++++++++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 packages/arrays/src/iterator.ts create mode 100644 packages/arrays/src/seq.ts create mode 100644 packages/arrays/test/iterator.ts create mode 100644 packages/arrays/test/seq.ts diff --git a/packages/arrays/src/index.ts b/packages/arrays/src/index.ts index ea9d7e854b..e1c87302fc 100644 --- a/packages/arrays/src/index.ts +++ b/packages/arrays/src/index.ts @@ -5,8 +5,10 @@ export * from "./ensure-iterable"; export * from "./find"; export * from "./fuzzy-match"; export * from "./is-sorted"; +export * from "./iterator"; export * from "./peek"; export * from "./quicksort"; +export * from "./seq"; export * from "./shuffle"; export * from "./starts-with"; export * from "./swap"; diff --git a/packages/arrays/src/iterator.ts b/packages/arrays/src/iterator.ts new file mode 100644 index 0000000000..69c938557e --- /dev/null +++ b/packages/arrays/src/iterator.ts @@ -0,0 +1,28 @@ +import { Nullable } from "@thi.ng/api"; + +/** + * Returns iterator of nullable array w/ optional index range support + * and/or reverse iteration order. The default range covers the entire + * array. + * + * @remarks + * If `start` > `end`, yields values in reverse order. No bounds + * checking is performed. + * + * @param buf - array or null + * @param start - start index + * @param end - end index (excluded) + */ +export function* arrayIterator( + buf: Nullable>, + start = 0, + end?: number +) { + if (!buf) return; + start = start; + end === undefined && (end = buf.length); + const step = start <= end ? 1 : -1; + for (; start !== end; start += step) { + yield buf[start]; + } +} diff --git a/packages/arrays/src/seq.ts b/packages/arrays/src/seq.ts new file mode 100644 index 0000000000..3f56355185 --- /dev/null +++ b/packages/arrays/src/seq.ts @@ -0,0 +1,30 @@ +import { ISeq, Nullable } from "@thi.ng/api"; + +/** + * Returns a zero-copy {@link @thi.ng/api#ISeq} for the given array and + * optionally defined index range. + * + * @remarks + * See {@link arrayIterator} for related functionality. + * + * @param buf - array + * @param start - start index + * @param end - end index (excluded) + */ +export const arraySeq = ( + buf: Nullable>, + start = 0, + end?: number +): ISeq => ({ + first() { + if (!buf) return; + end === undefined && (end = buf.length); + return start < end! ? buf[start] : undefined; + }, + next() { + if (!buf) return; + end === undefined && (end = buf.length); + const i = start + 1; + return i < end! ? arraySeq(buf, i, end) : undefined; + } +}); diff --git a/packages/arrays/test/iterator.ts b/packages/arrays/test/iterator.ts new file mode 100644 index 0000000000..d384bd8f6f --- /dev/null +++ b/packages/arrays/test/iterator.ts @@ -0,0 +1,13 @@ +import * as assert from "assert"; +import { arrayIterator } from "../src"; + +describe("arrayIterator", () => { + it("basics", () => { + assert.deepEqual([...arrayIterator(null)], []); + assert.deepEqual([...arrayIterator([])], []); + assert.deepEqual([...arrayIterator([1])], [1]); + assert.deepEqual([...arrayIterator([1, 2, 3, 4], 2)], [3, 4]); + assert.deepEqual([...arrayIterator([1, 2, 3, 4], 2, 3)], [3]); + assert.deepEqual([...arrayIterator([1, 2, 3, 4], 3, -1)], [4, 3, 2, 1]); + }); +}); diff --git a/packages/arrays/test/seq.ts b/packages/arrays/test/seq.ts new file mode 100644 index 0000000000..1656596958 --- /dev/null +++ b/packages/arrays/test/seq.ts @@ -0,0 +1,21 @@ +import * as assert from "assert"; +import { arraySeq } from "../src"; + +describe("arraySeq", () => { + it("basics", () => { + assert.notEqual(arraySeq(null), undefined); + assert.equal(arraySeq(null).first(), undefined); + assert.equal(arraySeq(null).next(), undefined); + assert.equal(arraySeq([]).first(), undefined); + assert.equal(arraySeq([]).next(), undefined); + assert.equal(arraySeq([1]).first(), 1); + assert.equal(arraySeq([1]).next(), undefined); + assert.equal(arraySeq([1, 2]).first(), 1); + // prettier-ignore + assert.equal(arraySeq([1, 2]).next()!.first(), 2); + // prettier-ignore + assert.equal(arraySeq([1, 2]).next()!.next(), undefined); + // prettier-ignore + assert.equal(arraySeq([1, 2, 3]).next()!.next()!.first(), 3); + }); +});