1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 |
x4
x4
x21
x21
x20
x20
x21
x18
x18
x18
x20
x21
x14
x14
x14
x28
x28
x14
x14
x18
x13
x13
x23
x23
x13
x13
x6
x21 |
|
// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.
/**
* Builds N-tuples of elements from the given N iterables with matching
* indices, stopping when the shortest iterable is exhausted.
*
* Notes:
* - Inputs are consumed eagerly. Non-array iterables are materialized via
* `Array.from` before zipping, so passing an infinite iterable (such as an
* unbounded generator) will hang.
* - Strings are iterables of code points. Passing a string zips it
* character-by-character rather than treating it as a single scalar value.
*
* @experimental **UNSTABLE**: New API, yet to be vetted.
*
* @typeParam T The tuple of element types in the input iterables.
*
* @param iterables The iterables to zip.
*
* @returns A new array containing N-tuples of elements from the given
* iterables.
*
* @example Basic usage
* ```ts
* import { zip } from "@std/collections/unstable-zip";
* import { assertEquals } from "@std/assert";
*
* const numbers = [1, 2, 3, 4];
* const letters = ["a", "b", "c", "d"];
* const pairs = zip(numbers, letters);
*
* assertEquals(
* pairs,
* [
* [1, "a"],
* [2, "b"],
* [3, "c"],
* [4, "d"],
* ],
* );
* ```
*
* @example With iterables
* ```ts
* import { zip } from "@std/collections/unstable-zip";
* import { assertEquals } from "@std/assert";
*
* assertEquals(
* zip(new Set([1, 2, 3]), ["a", "b", "c"]),
* [[1, "a"], [2, "b"], [3, "c"]],
* );
* ```
*
* @example Strings are iterables
* ```ts
* import { zip } from "@std/collections/unstable-zip";
* import { assertEquals } from "@std/assert";
*
* // A string is zipped character-by-character, not as a single value.
* assertEquals(
* zip("abc", [1, 2, 3]),
* [["a", 1], ["b", 2], ["c", 3]],
* );
* ```
*/
export function zip<T extends unknown[]>(
...iterables: { [K in keyof T]: Iterable<T[K]> }
): T[] {
const arrayCount = iterables.length;
if (arrayCount === 0) return [];
const arrays = iterables.map((it) => Array.isArray(it) ? it : Array.from(it));
let minLength = arrays[0]!.length;
for (let i = 1; i < arrayCount; ++i) {
const len = arrays[i]!.length;
if (len < minLength) minLength = len;
}
const result: T[] = new Array(minLength);
// Fast path for two iterables
if (arrayCount === 2) {
const a = arrays[0]!;
const b = arrays[1]!;
for (let i = 0; i < minLength; ++i) {
result[i] = [a[i], b[i]] as T;
}
return result;
}
for (let i = 0; i < minLength; ++i) {
const tuple: unknown[] = new Array(arrayCount);
for (let j = 0; j < arrayCount; ++j) {
tuple[j] = arrays[j]![i];
}
result[i] = tuple as T;
}
return result;
}
|