Skip to the code
cf.

zip and unzip

Write zip(...arrays). It takes any number of arrays and returns an array of tuples (small arrays): tuple i holds item i of each array, in the order the arrays were passed.

The result is as long as the longest array. Where a shorter array has run out, its place in the tuple holds undefined, as a real entry, not a hole. With no arrays, or only empty ones, zip returns [].

Write unzip(tuples), which does the reverse: it takes an array of tuples and returns one array per position. Tuples may have different lengths; unzip pads with undefined the same way, so the result has as many arrays as the longest tuple has items.

Neither function changes its input.

zip([1, 2, 3], ["a", "b", "c"]); // [[1, "a"], [2, "b"], [3, "c"]]
zip([1, 2], ["a"], [true]);      // [[1, "a", true], [2, undefined, undefined]]
zip();                           // []
 
unzip([[1, "a"], [2, "b"]]);     // [[1, 2], ["a", "b"]]
unzip([[1, "a", true], [2]]);    // [[1, 2], ["a", undefined], [true, undefined]]

What the tests check

  1. zip pairs items by index
    expect(zip([1, 2, 3], ["a", "b", "c"])).toEqual([[1, "a"], [2, "b"], [3, "c"]]);
    
  2. zip takes any number of arrays
    expect(zip([1, 2], [3, 4], [5, 6])).toEqual([[1, 3, 5], [2, 4, 6]]);
    expect(zip(["a", "b"])).toEqual([["a"], ["b"]]);
    
  3. zip is as long as the longest array, padded with undefined
    expect(zip([1, 2, 3], ["a"])).toEqual([[1, "a"], [2, undefined], [3, undefined]]);
    expect(zip(["a"], [1, 2, 3])).toEqual([["a", 1], [undefined, 2], [undefined, 3]]);
    
  4. zip pads with real undefined entries, not holes
    const tuples = zip([1, 2], ["a"]);
    expect(tuples[1]).toHaveLength(2);
    expect(1 in tuples[1]).toBe(true);
    const [first] = zip([], [1]);
    expect(first).toHaveLength(2);
    expect(0 in first).toBe(true);
    
  5. zip returns [] with no arrays or only empty ones
    expect(zip()).toEqual([]);
    expect(zip([], [])).toEqual([]);
    
  6. unzip regroups tuples by position
    expect(unzip([[1, "a"], [2, "b"], [3, "c"]])).toEqual([[1, 2, 3], ["a", "b", "c"]]);
    expect(unzip([])).toEqual([]);
    
  7. unzip undoes zip
    const ids = [1, 2, 3];
    const names = ["Ada", "Lin", "Cy"];
    const admins = [true, false, true];
    expect(unzip(zip(ids, names, admins))).toEqual([ids, names, admins]);
    
  8. unzip pads tuples of different lengths with undefined
    expect(unzip([[1, "a", true], [2]])).toEqual([[1, 2], ["a", undefined], [true, undefined]]);
    const result = unzip([[1], [2, "b"]]);
    expect(result).toEqual([[1, 2], [undefined, "b"]]);
    expect(0 in result[1]).toBe(true);
    
  9. neither changes its input
    const a = [1, 2];
    const b = ["x"];
    zip(a, b);
    expect(a).toEqual([1, 2]);
    expect(b).toEqual(["x"]);
    const tuples = [[1, "a"], [2]];
    unzip(tuples);
    expect(tuples).toEqual([[1, "a"], [2]]);
    

Learn more

solution.jsSaved in this browser

Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.

Ctrl + Enter runs the tests (⌘ + Enter on a Mac).