How do I zip two arrays in JavaScript?

I have 2 arrays:

var a = [1, 2, 3]
var b = [a, b, c]

What I want to get as a result is:

[[1, a], [2, b], [3, c]]

It seems simple but I just can't figure out.

I want the result to be one array with each of the elements from the two arrays zipped together.

2

3 Answers

Use the map method:

var a = [1, 2, 3]
var b = ['a', 'b', 'c']
var c = a.map(function(e, i) { return [e, b[i]];
});
console.log(c)

DEMO

13

Zip Arrays of same length:

Using Array.prototype.map()

const zip = (a, b) => a.map((k, i) => [k, b[i]]);
console.log(zip([1,2,3], ["a","b","c"]));
// [[1, "a"], [2, "b"], [3, "c"]]

Zip Arrays of different length:

Using Array.from()

const zip = (a, b) => Array.from(Array(Math.max(b.length, a.length)), (_, i) => [a[i], b[i]]);
console.log( zip([1,2,3], ["a","b","c","d"]) );
// [[1, "a"], [2, "b"], [3, "c"], [undefined, "d"]]

Using Array.prototype.fill() and Array.prototype.map()

const zip = (a, b) => Array(Math.max(b.length, a.length)).fill().map((_,i) => [a[i], b[i]]);
console.log(zip([1,2,3], ["a","b","c","d"]));
// [[1, "a"], [2, "b"], [3, "c"], [undefined, "d"]]

Zip Multiple (n) Arrays:

const zip = (...arr) => Array(Math.max(...arr.map(a => a.length))).fill().map((_,i) => arr.map(a => a[i]));
console.log(zip([1,2], [3,4], [5,6])); // [[1,3,5], [2,4,6]]
8

Zipping by leveraging generator functions

You can also use a generator function to zip().

const a = [1, 2, 3]
const b = ['a', 'b', 'c']
/** * Zips any number of arrays. It will always zip() the largest array returning undefined for shorter arrays. * @param {...Array<any>} arrays */
function* zip(...arrays){ const maxLength = arrays.reduce((max, curIterable) => curIterable.length > max ? curIterable.length: max, 0); for (let i = 0; i < maxLength; i++) { yield arrays.map(array => array[i]); }
}
// put zipped result in an array
const result = [...zip(a, b)]
// or lazy generate the values
for (const [valA, valB] of zip(a, b)) { console.log(`${valA}: ${valB}`);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }

The above works for any number of arrays and will zip() the longest array so undefined is returned as a value for shorter arrays.

Zipping of all Iterables

Here a function which can be used for all Iterables (e.g. Maps, Sets or your custom Iterable), not just arrays.

const a = [1, 2, 3];
const b = ["a", "b", "c"];
/** * Zips any number of iterables. It will always zip() the largest Iterable returning undefined for shorter arrays. * @param {...Iterable<any>} iterables */
function* zip(...iterables) { // get the iterator of for each iterables const iters = [...iterables].map((iterable) => iterable[Symbol.iterator]()); let next = iters.map((iter) => iter.next().value); // as long as any of the iterables returns something, yield a value (zip longest) while(anyOf(next)) { yield next; next = iters.map((iter) => iter.next().value); } function anyOf(arr){ return arr.some(v => v !== undefined); }
}
// put zipped result in aa array
const result = [...zip(a, new Set(b))];
// or lazy generate the values
for (const [valA, valB] of zip(a, new Set(b))) { console.log(`${valA}: ${valB}`);
}

Obviously it would also be possible to just use [...Iterable] to transform any Iterable to an array and then use the first function.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like