zip together a list of input iterators or iterable objects as tuples, similar to python's zip function.

Note

this zip function stops yielding as soon as one of its input iterators is "done" iterating (i.e. out of elements).

if all of your input iterators are arrays, then use the zipArrays function, which is more performant (and smaller in footprint).

a tuple of each entry from the given list of iterators, until one of the iterators is "done" iterating (i.e. out of elements).

import { assertEquals } from "jsr:@std/assert"

type MyObj = { key: string }
type MyTuple = [number, boolean, MyObj]

const
my_num_iter: Iterable<number> = rangeIterator(100), // infnite iterable, with values `[100, 101, 102, ...]`
my_bool_iter: Iterator<boolean> = [true, false, false, true, false][Symbol.iterator](),
my_obj_iter: Iterable<MyObj> = [{ key: "a" }, { key: "b" }, { key: "c" }, { key: "d" }]
// notice that `my_obj_iter` is shorter than the other two arrays. (i.e. has a length of `4`)
// this would mean that zipping them together would only generate a 3-tuple array of `4` elements.

const my_tuples_iter: Iterator<MyTuple> = zipIterators<[number, boolean, MyObj]>(my_num_iter, my_bool_iter, my_obj_iter)
assertEquals(my_tuples_iter.next(), { value: [100, true, { key: "a" }], done: false })
assertEquals(my_tuples_iter.next(), { value: [101, false, { key: "b" }], done: false })
assertEquals(my_tuples_iter.next(), { value: [102, false, { key: "c" }], done: false })
assertEquals(my_tuples_iter.next(), { value: [103, true, { key: "d" }], done: false })
assertEquals(my_tuples_iter.next(), { value: 4, done: true }) // the return value of the iterator dictates its length.


// since the actual output of `zipIterators` is an `IterableIterator`,
// so we may even use it in a for-of loop, or do an array spreading with the output.
const my_tuples_iter2 = zipIterators<[number, boolean]>(my_num_iter, [false, true, false, false, true])
my_tuples_iter2 satisfies Iterable<[number, boolean]>

// IMPORTANT: notice that the first tuple is not `[104, false]`, but instead `[105, false]`.
// this is because our first zip iterator (`my_tuples_iter`) utilized the `my_num_iter` iterable one additional time
// before realizing that one of the input iterables (the `my_bool_iter`) had gone out of elements to provide.
// thus, the ordering of the iterators do matter, and it is possible to have one iterated value to disappear into the void.
assertEquals([...my_tuples_iter2], [
[105, false],
[106, true ],
[107, false],
[108, false],
[109, true ],
])

// zipping with zero sized input iterators should not yield anything.
assertEquals([...zipIterators([], [], [])], [])

// zipping with no input iterators at all should not iterate infinitely.
assertEquals([...zipIterators()], [])
  • Type Parameters

    • T extends any[]

    Parameters

    • ...iterators: (Iterable | Iterator)[]

      the list of iterators/iterable objects which should be zipped.

    Returns IterableIterator<T, number>

    the number of items that were yielded/iterated (i.e. length of iterator).