|
1 | 1 | /** |
2 | 2 | * Zips multiple iterables into a single iterable. |
3 | 3 | * |
| 4 | + * The resulting iterable will yield arrays of elements from the input iterables. |
| 5 | + * The first array will contain the first element of each input iterable, the second array will contain the second element of each input iterable, and so on. |
| 6 | + * |
| 7 | + * If the input iterables have different lengths, the resulting iterable will stop when the shortest input iterable is exhausted. |
| 8 | + * The remaining elements from the longer input iterables will be ignored. |
| 9 | + * |
| 10 | + * Use {@linkcode https://jsr.io/@core/iterutil/async/chain chain} to chain iterables. |
| 11 | + * Use {@linkcode https://jsr.io/@core/iterutil/async/enumerate enumerate} to zip with indices. |
| 12 | + * Use {@linkcode https://jsr.io/@core/iterutil/zip zip} to zip iterables synchronously. |
| 13 | + * |
4 | 14 | * @param iterables The iterables to zip. |
5 | 15 | * @returns The zipped iterable. |
6 | 16 | * |
7 | 17 | * @example |
8 | 18 | * ```ts |
9 | 19 | * import { zip } from "@core/iterutil/async/zip"; |
10 | 20 | * |
11 | | - * const iter = zip([1, 2, 3], ["a", "b", "c"]); |
12 | | - * console.log(await Array.fromAsync(iter)); // [[1, "a"], [2, "b"], [3, "c"]] |
| 21 | + * const iter = zip( |
| 22 | + * [1, 2, 3], |
| 23 | + * ["a", "b", "c"], |
| 24 | + * [true, false, true], |
| 25 | + * ); |
| 26 | + * console.log(await Array.fromAsync(iter)); // [[1, "a", true], [2, "b", false], [3, "c", true]] |
13 | 27 | * ``` |
14 | 28 | */ |
15 | 29 | export async function* zip< |
16 | | - U extends (Iterable<unknown> | AsyncIterable<unknown>)[], |
| 30 | + U extends readonly [ |
| 31 | + Iterable<unknown> | AsyncIterable<unknown>, |
| 32 | + Iterable<unknown> | AsyncIterable<unknown>, |
| 33 | + ...(Iterable<unknown> | AsyncIterable<unknown>)[], |
| 34 | + ], |
17 | 35 | >( |
18 | 36 | ...iterables: U |
19 | 37 | ): AsyncIterable<Zip<U>> { |
20 | | - const its = iterables.map((iterable) => |
21 | | - Symbol.iterator in iterable |
22 | | - ? iterable[Symbol.iterator]() |
23 | | - : iterable[Symbol.asyncIterator]() |
| 38 | + const iterators = iterables.map((it) => |
| 39 | + Symbol.iterator in it ? it[Symbol.iterator]() : it[Symbol.asyncIterator]() |
24 | 40 | ); |
25 | 41 | while (true) { |
26 | | - const rs = await Promise.all(its.map((it) => it.next())); |
27 | | - if (rs.find(({ done }) => !!done)) { |
| 42 | + const results = await Promise.all(iterators.map((it) => it.next())); |
| 43 | + if (results.find(({ done }) => !!done)) { |
28 | 44 | break; |
29 | 45 | } |
30 | | - yield rs.map(({ value }) => value) as Zip<U>; |
| 46 | + yield results.map(({ value }) => value) as Zip<U>; |
31 | 47 | } |
32 | 48 | } |
33 | 49 |
|
34 | 50 | /** |
35 | 51 | * @internal |
36 | 52 | */ |
37 | | -export type Zip<T extends (Iterable<unknown> | AsyncIterable<unknown>)[]> = { |
| 53 | +export type Zip< |
| 54 | + T extends readonly (Iterable<unknown> | AsyncIterable<unknown>)[], |
| 55 | +> = { |
38 | 56 | [P in keyof T]: T[P] extends Iterable<infer U> ? U |
39 | 57 | : T[P] extends AsyncIterable<infer U> ? U |
40 | 58 | : never; |
|
0 commit comments