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');