diff --git a/src/lib.ts b/src/lib.ts index ba3c6d8..102cc4e 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -2,7 +2,7 @@ export type { Arr, ClassOf, Constructible, Function, InstanceOf, KeyOfType, Tail } from "./lib/types.ts"; // functions -export { all, enumerate, filter, filter_map, it, Iter, map, zip } from "./lib/iter.ts"; +export { all, chunk, enumerate, filter, filter_map, it, Iter, map, window, zip } from "./lib/iter.ts"; export { log_from, next, split_promise, wait } from "./lib/utils.ts"; // Structures diff --git a/src/lib/iter.ts b/src/lib/iter.ts index 34a7ef5..5fceb58 100644 --- a/src/lib/iter.ts +++ b/src/lib/iter.ts @@ -40,6 +40,33 @@ export function* zip(a: Iterable, b: Iterable): Generator<[A, B], vo } } +export function* chunk(iter: Iterable, size: number, incomplete = true): Generator { + let chunk = [] as T[]; + for (const item of iter) { + if (chunk.length === size) { + yield chunk; + chunk = []; + } + chunk.push(item); + } + if (incomplete) yield chunk; +} + +export function* window(iter: Iterable, size: number, incomplete = false): Generator { + const window = [] as T[]; + for (const item of iter) { + window.push(item); + if (window.length > size) window.splice(0, 1); + if (incomplete || window.length === size) yield [...window]; + } + if (incomplete) { + for (const _ in range(0, window.length)) { + window.splice(0, 1); + yield [...window]; + } + } +} + export class Iter { iter; [Symbol.iterator] = () => this.iter[Symbol.iterator](); @@ -68,7 +95,19 @@ export class Iter { return new Iter(zip(this, other)); } + chunk(size: number, incomplete = true) { + return new Iter(chunk(this, size, incomplete)); + } + + window(size: number, incomplete = false) { + return new Iter(window(this, size, incomplete)); + } + array() { + return [...this]; + } + + array_it() { // deno-lint-ignore no-explicit-any const result: any = [...this]; result.it = () => it(result); @@ -76,7 +115,7 @@ export class Iter { } collect(class_: new (it: Iterable) => O): O { - return new class_(this); + return new class_(this.iter); } all(predicate: (item: T) => boolean) { @@ -84,7 +123,8 @@ export class Iter { } } -Deno.test("iter", async () => { +Deno.test("test_comon", async () => { + const { assertEquals } = await import("https://deno.land/std@0.224.0/assert/assert_equals.ts"); const items = it(range(0, 10)) .map((e) => e * 3) .enumerate() @@ -92,7 +132,19 @@ Deno.test("iter", async () => { .zip(range(0, 10)) .map(JSON.stringify) .collect(Set); - - const { assertEquals } = await import("https://deno.land/std@0.224.0/assert/assert_equals.ts"); assertEquals(items, new Set(["[[1,3],0]", "[[3,9],1]", "[[5,15],2]", "[[7,21],3]", "[[9,27],4]"])); }); + +Deno.test("test_chunk", async () => { + const { assertEquals } = await import("https://deno.land/std@0.224.0/assert/assert_equals.ts"); + const items = it(range(0, 5)).chunk(2).array(); + assertEquals(items, [[0, 1], [2, 3], [4]]); +}); + +Deno.test("test_window", async () => { + const { assertEquals } = await import("https://deno.land/std@0.224.0/assert/assert_equals.ts"); + const items = it(range(0, 5)).window(3).array(); + assertEquals(items, [[0, 1, 2], [1, 2, 3], [2, 3, 4]]); + const items_incomplete = it(range(0, 3)).window(3, true).array(); + assertEquals(items_incomplete, [[0], [0, 1], [0, 1, 2], [1, 2], [2]]); +});