How to scale a two dimensional array in javascript fast?

Here's a very reduced way, using Array().fill, It's running faster than the other answers at least in my browser.

I added two versions, one using spread operator, and the other ussing .apply. I'm getting faster results with apply.

function scaleSpread(array, factor) {
	const scaled = [];

	for(const row of array) {
		let x = [];

		for(const item of row)
			x.push(...Array(factor).fill(item));

		scaled.push(...Array(factor).fill(x));
	}

	return scaled;
}

function scaleApply(array, factor) {
	const scaled = [];

	for(const row of array) {
		let x = [];

		for(const item of row)
			x.push.apply(x, Array(factor).fill(item));

		scaled.push.apply(scaled, Array(factor).fill(x));
	}

	return scaled;
}

function scaleConcat(array, factor) {
	let scaled = [];

	for(const row of array) {
		let x = [];

		for(const item of row)
			x = x.concat(Array(factor).fill(item));

		scaled = scaled.concat(Array(factor).fill(x));
	}

	return scaled;
}

var a = [ [0, 0, 1, 0], [0, 1, 1, 1],  [0, 0, 1, 0],  [0, 0, 1, 1] ]

console.time('spread');
scaleSpread(a, 10000);
console.timeEnd('spread');

console.time('apply');
scaleApply(a, 10000);
console.timeEnd('apply');

console.time('concat');
scaleConcat(a, 10000);
console.timeEnd('concat');

EDIT: Added a version using .concat since apply and spread causes Maximum call stack size exceeded with very large arrays.


This approach is using a for loop, to iterate an n-dimensional array for the decided n times.

This uses Array.splice method, by grabbing the source value and inserting it to the array at certain index.

PS: The source array (which is a), is mutated here. But, you can always clone the original array and create b for the result as you wanted.

var a = [
    [0, 0, 1, 0],
    [0, 1, 1, 1], 
    [0, 0, 1, 0], 
    [0, 0, 1, 1] 
  ],
  scale = 4,
  scaleTheArray = function (arrayToScale, nTimes) {
    for (var idx = 0, i = 0, len = arrayToScale.length * nTimes; i < len; i++) {
      var elem = arrayToScale[idx];

      /* Insert the element into (idx + 1) */
      arrayToScale.splice(idx + 1, 0, elem);

      /* Add idx for the next elements */
      if ((i + 1) % nTimes === 0) {
        idx += nTimes + 1;
      }
    }
  };

console.time('testScale');

/* 1. Expand each of the a[n] length */
for (var i = 0, len = a.length; i < len; i++) {
  var arr = a[i];

  scaleTheArray(arr, scale - 1);
}

/* 2. Expand each of the a length */
scaleTheArray(a, scale - 1);

console.timeEnd('testScale');