Zip 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

6 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.

Using the reduce method:

const a = [1, 2, 3]
const b = ['a', 'b', 'c']
var c = a.reduce((acc, curr, ind) => { acc.push([curr, b[ind]]); return acc;
}, []);
console.log(c)

With forEach method:

const a = [1, 2, 3]
const b = ['a', 'b', 'c']
const c = [];
a.forEach((el, ind) => { c.push([el, b[ind]])
});
console.log(c)

Providing a solution with imperative programming by a simple for loop.

This performs better when doing the zip operation on huge data sets compared to the convenient array functions like map() and forEach().

Example:

const a = [1, 2, 3];
const b = ['a', 'b', 'c'];
const result = [];
for (let i = 0; i < a.length; i++) { result.push([a[i], b[i]]);
}
console.log(result);

And if you want a 1 line simpler solution then you can use a library like ramda which has a zip function.

Example:

const a = [1, 2, 3];
const b = ['a', 'b', 'c'];
const result = R.zip(a, b);
console.log(result);

Zip function for 2D arrays

Here is a function that zips multiple arrays. However, It only works with 2D arrays only.

function zip(listOfLists) { return listOfLists[0].map((value, index) => { let result = []; for(let i=0; i <= listOfLists.length-1 ; i++){ result[i] = listOfLists[i][index] } return result; });
}

This is how you run it.

console.log( zip( [[1, 2, 3], [4, 5, 6], [7, 8, 9]] )
);

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 and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like