I have two arrays in JavaScript, of potentially different lengths:
var x = ['a', 'b', 'c'];
var y = ['g', 'h', 'i', 'j'];
I'd like to bine them into one array:
var z = ['a', 'g', 'b', 'h', 'c', 'i', 'j'];
How can I do that in JavaScript?
I have two arrays in JavaScript, of potentially different lengths:
var x = ['a', 'b', 'c'];
var y = ['g', 'h', 'i', 'j'];
I'd like to bine them into one array:
var z = ['a', 'g', 'b', 'h', 'c', 'i', 'j'];
How can I do that in JavaScript?
Share Improve this question asked Nov 2, 2016 at 9:52 Andrew FerrierAndrew Ferrier 17.8k14 gold badges54 silver badges78 bronze badges7 Answers
Reset to default 7I see you answered your question at the same time as asking it. That's fine, but it's now clear that you were looking for a solution that leverages a library (eg, lodash) and not necessarily one that teaches you how to build such a procedure. In retrospect, I would've answered this differently, but nevertheless I think you can learn something from this answer.
I would remend calling this something other than zip
just because zip
is used as name for a procedure that does something quite different from what you're looking for.
Here's a simple recursive definition of interleave
-
const interleave = ([ x, ...xs ], ys = []) =>
x === undefined
? ys // base: no x
: [ x, ...interleave (ys, xs) ] // inductive: some x
const xs = [ 'a', 'b', 'c' ]
const ys = [ 'g', 'h', 'i', 'j' ]
console .log (interleave (xs, ys))
// [ a, g, b, h, c, i, j ]
And another variation that supports any number of input arrays -
const interleave = ([ x, ...xs ], ...rest) =>
x === undefined
? rest.length === 0
? [] // base: no x, no rest
: interleave (...rest) // inductive: no x, some rest
: [ x, ...interleave (...rest, xs) ] // inductive: some x, some rest
const ws = [ '0', '1', '2', '3' ]
const xs = [ 'a', 'b', 'c' ]
const ys = [ 'd', 'e', 'f' ]
const zs = [ 'g', 'h', 'i', 'j' ]
console .log (interleave (ws, xs, ys, zs))
// [ 0, a, d, g, 1, b, e, h, 2, c, f, i, 3, j ]
tl;dr: z = _.flatten(_.zip(x, y)).filter(element => element)
, as long as you don't care about null elements in the original arrays.
Some of the libraries providing functional tools, such as Lodash, provide enough mechanics to easily do this. For example, you can do this:
var z1 = _.zip(x, y);
// z1 is now [["a","g"],["b","h"],["c","i"],[null,"j"]]
var z2 = _.flatten(z1);
// z2 is now ["a","g","b","h","c","i",null,"j"]
var z3 = z2.filter(element => element)
// z3 is now ["a","g","b","h","c","i","j"]
Note that this will only work if the original arrays do not contain any null elements, as they are filtered out by the last step.
A simple implementation that will stitch the arrays:
function stitch(x, y) {
var arr = [];
var length = Math.max(x.length, y.length);
for(var i = 0; i < length; i++) {
i < x.length && arr.push(x[i]);
i < y.length && arr.push(y[i]);
}
return arr;
}
var x = ['a', 'b', 'c'];
var y = ['g', 'h', 'i', 'j'];
console.log(stitch(x, y));
This is the functional way to address the problem:
var x = ['a', 'b', 'c'];
var y = ['g', 'h', 'i', 'j'];
function stitch(x,y) {
var a = x.length > y.length ? x : y;
var b = x.length > y.length ? y : x;
var c = a.map(function (e, i) {
return b.length<i ? [e, b[i]] : [];
});
return [].concat.apply([],c)
}
Here's a very simple recursive solution:
const interlace = (xxs, ys) => {
if (xxs.length === 0) return ys;
const [x, ...xs] = xxs;
return [x, ...interlace(ys, xs)];
};
const xs = ['a', 'b', 'c'];
const ys = ['g', 'h', 'i', 'j'];
console.log(JSON.stringify(interlace(xs, ys)));
In addition, you can easily generalize this algorithm to an arbitrary number of arrays:
const interlace = (...xss) => xss.length > 0 ? interleave(...xss) : [];
const interleave = (xxs, ...yss) => {
if (xxs.length === 0) return interlace(...yss);
const [x, ...xs] = xxs;
return [x, ...interleave(...yss, xs)];
};
const xs = ['a', 'b', 'c'];
const ys = ['g', 'h', 'i', 'j'];
const zs = ['d', 'e', 'f'];
console.log(JSON.stringify(interlace()));
console.log(JSON.stringify(interlace(xs)));
console.log(JSON.stringify(interlace(xs, ys)));
console.log(JSON.stringify(interlace(xs, ys, zs)));
Hope that helps.
This can be done in regular Javascript. No need for fancy tricks:
function splicer(array, element, index) {
array.splice(index * 2, 0, element);
return array;
}
function weave(array1, array2) {
return array1.reduce(splicer, array2.slice());
}
var x = ['a', 'b', 'c'];
var y = ['g', 'h', 'i', 'j'];
var z = weave(x, y);
console.log(z);
var x = ['a', 'b', 'c'];
var y = ['g', 'h', 'i', 'j'];
var z=[];
if(y.length>=x.length){
for(var i=0;i<x.length;i++){
z.push(x[i]);
z.push(y[i]);
}
while(i<y.length)
z.push(y[i++]);
}else{
for(var i=0;i<y.length;i++){
z.push(x[i]);
z.push(y[i]);
}
while(i<x.length)
z.push(x[i++]);
}
window.alert(JSON.stringify(z)); // print ["a","g","b","h","c","i","j"]