add iterating over grouped items of iterators

This commit is contained in:
Matthieu Jolimaitre 2024-09-11 10:28:36 +02:00
parent 12f109adf3
commit 0b464ba8a3
2 changed files with 57 additions and 5 deletions

View file

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

View file

@ -40,6 +40,33 @@ export function* zip<A, B>(a: Iterable<A>, b: Iterable<B>): Generator<[A, B], vo
}
}
export function* chunk<T>(iter: Iterable<T>, size: number, incomplete = true): Generator<T[], void, void> {
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<T>(iter: Iterable<T>, size: number, incomplete = false): Generator<T[], void, void> {
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<T> {
iter;
[Symbol.iterator] = () => this.iter[Symbol.iterator]();
@ -68,7 +95,19 @@ export class Iter<T> {
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<T> {
}
collect<O>(class_: new (it: Iterable<T>) => O): O {
return new class_(this);
return new class_(this.iter);
}
all(predicate: (item: T) => boolean) {
@ -84,7 +123,8 @@ export class Iter<T> {
}
}
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<string>);
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]]);
});