Allow Zip and Unzip to work on more than two arrays
See original GitHub issuePrevious discussion for this issue here: https://github.com/denoland/deno_std/discussions/970#discussioncomment-1272939
Is your feature request related to a problem? Please describe. Currently, zip and unzip in std/collections follow this type signature, which means they operate on two arrays in the case of zip or an array of pairs, in the case of unzip.
function zip<T, U>(array: readonly T[], withArray: readonly U[]): [T, U][];
function unzip<T, U>(pairs: readonly [T, U][]): [T[], U[]]
Describe the solution you’d like I’d like it if zip could work on more than two arrays at a time, and if unzip could work on more than an array of pairs.
Describe alternatives you’ve considered There are two ways forward: Either use varargs to accept as many arrays as possible like this and zip them up:
function variadicZip<T = any>(...arrays: (readonly T[])[]): T[] {
const arrLength = arrays.map(i => i.length);
const returnLength = Math.min(...arrLength);
const ret = new Array<any>(returnLength);
for (let i = 0; i < returnLength; i += 1) {
const arr = [];
for (const array of arrays) {
arr.push(array[i]);
}
ret[i] = arr;
}
return ret;
}
or to overload zip to take up to 10 arrays and return a zip of the arrays provided (implemented for 2 + 3 arrays). This has the advantage that it provides the caller with more type information (you get back an array of [T, U][]
if you zip with two arrays, whereas with the previous implementation, you would get back an array of [any][]
.
function zip<T, U>(
array1: readonly T[],
array2: readonly U[]
): [T, U][] {
const returnLength = Math.min(array1.length, array2.length);
const ret = new Array<[T, U]>(returnLength);
for (let i = 0; i < returnLength; i += 1) {
ret[i] = [array1[i], array2[i]];
}
return ret;
}
function zip<T, U, V>(
array1: readonly T[],
array2: readonly U[],
array3: readonly V[]
): [T, U, V][] {
const returnLength = Math.min(...[array1.length, array2.length, array3.length]);
const ret = new Array<[T, U, V]>(returnLength);
for (let i = 0; i < returnLength; i += 1) {
ret[i] = [array1[i], array2[i], array3[i]];
}
return ret;
}
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (6 by maintainers)
There’s no need for a compromise here, it’s very possible to have well-typed variadic zips:
@Takashiidobe I found that your implementation incorrectly infers
foo
to be[number[], string[], boolean[]]
when I put it into my example.Variadic unzip could be typed as such:
However, it might end up being a breaking change, since
[]
would no longer unzip to[[], []]
.