zip-iterables
v2.0.0
Published
Convert an array of iterables to an iterable of arrays
Downloads
7
Readme
zip-iterables
This package provides:
- A
zip
function that converts an array ofIterable
s into anIterable
of arrays. zipAsync
andzipAsyncParallel
functions that do the same forAsyncIterable
s.- TypeScript overloads for n-tuples, such as
<A, B>(Iterable<A>, Iterable<B>) => Iterable<[A, B]>
. - Some utilities such as:
asyncIterableToArray()
iterableToAsyncIterable()
isAsyncIterable()
andisIterable()
iteratorReturn()
,iteratorThrow()
,asyncIteratorReturn()
andasyncIteratorThrow()
Example
import { zip } from "zip-iterables";
Array.from(zip(["a", "b", "c"], ["d", "e"], [1, 2]));
// Result:
// [
// ['a', 'd', 1],
// ['b', 'e', 2]
// ]
Why this package?
It is fairly trivial to implement a basic zip
function:
// Example only. Do not do this in production.
function* zip<T>(...iterables: Iterable<T>[]): Iterable<T> {
const iters = iterables.map(x => x[Symbol.iterator]());
while (true) {
const ret = new Array<T>();
for (const iter of iters) {
const { done, value } = iter.next();
if (done) {
return;
}
ret.push(value);
}
yield ret;
}
}
However, the functions provided by this package have a number of important advantages over a naive implementation:
- The resulting
Iterable
orAsyncIterable
can be looped over multiple times (i.e. it returns a fresh iterator in response to[Symbol.iterator]()
and[Symbol.asyncIterator]()
). This would not be the case ifzip
itself is a generator function (as above). - All three of the
next
,return
andthrow
methods, instead of justnext
, are forwarded to the inner iterators and the results collated. - Return values (
value
of theIteratorResult
whendone = true
) are also collated from inner iterators in addition to yielded values, withundefined
used as the value for iterators that have not finished. - As soon as
next
,return
orthrow
on one of the iterators either throws or returnsdone = true
, the other iterators are closed by calling thereturn
method, if defined. This gives the iterator an opportunity to free any resources so they do not leak. For example, if the iterator is a generator, this executes anyfinally {..}
blocks around the currentyield
. - If any of the iterators throw in response to
return
, this does not preventreturn
from being called on the other iterators. - If any of the iterators throw and an error has already been caught, the original error is re-thrown instead of the
new one. (This is what TypeScript and Babel do for a
for...of
loop.) - The
return
method is only called on iterators that have started (next
called at least once) but not finished (next
has not returneddone = true
) and not thrown. (This is what TypeScript and Babel do for afor...of
loop.) - Any input passed to the zipped iterator via the
next
,return
andthrow
methods is forwarded to the individual iterators. - For
zipAsyncParallel
, thenext
,return
andthrow
methods of theAsyncIterator
s are executed in parallel to maximise throughput.