As already mentioned here a few times, the simplest way to do this is
function intercalate(glue, arr){
return arr.reduce((acc, v) => acc.concat(glue, v));
}
but this is not the best way, since it creates with every iteration a new (intermediate) array, that is then thrown away. This doesn't matter for this short array of values, but if you ever intend to use this on a longer Array, you might notice the impact.
Better would be to create one Array and push the values into that, as they come in.
function intercalate(glue, arr){
const push = (acc, v) => (Array.isArray(v)? acc.push(...v): acc.push(v), acc);
return arr.reduce((acc, v, i) => push(i===0? acc: push(acc, glue), v), []);
}
But since this Array is gradually increasing it may still need to allocate a bigger chunk of memory and copy the data. These tasks ar very performant, but still unnecessary (imo); we can do better.
We first create a list containing all Arrays and the delimiter in between, and flatten this by using concat.apply([], list)
. Therefore we produce one intermediate Array, who's size we can compute ahead of time, and the rest is the problem of Array.concat, and it's underlying implementation.
function intersperse(delimiter, arr){
if(!arr.length) return [];
let j = 0, push = (acc, v) => (acc[j++] = v, acc);
return arr.reduce((acc, v) => push(j===0? acc: push(delimiter, glue), v), Array(2*arr.length-1));
}
//or
function intersperse(delimiter, arr){
if(!arr.length) return [];
var out = Array(2*arr.length-1);
out[0] = arr[0];
for(var i=1, j=1; j<out.length;){
out[j++] = delimiter;
out[j++] = arr[i++];
}
return out;
}
//and
function intercalate(glue, arr){
var emptyArray = [];
return arr.length?
emptyArray.concat.apply(emptyArray, intersperse(glue, arr)):
emptyArray;
}
Wich version will be the best/fastest, in the end, is not that easy to tell, since it may depend on the passed values, and wether or not the JIT compiler optimizes the s*** out of it. I made my points, it's up to you to choose wich version/implementation you use.
To the first version: you may prefer to not put this into a lib at all, but write it mostly inline (it's short and simple enough for that), therefore the JIT-compiler may not try to find some common types between the different calls (#monomorphic function/code) and therefore optimize each occurance seperately. On the other hand, this could be premature optimization. It's up to you.