A matrix having at least one dimension equal to zero is called an empty matrix. The simplest empty matrix is 0-by-0 in size. Examples of more complex matrices are those of dimension 0 -by- 5 or 10 -by- 0 -by- 20.
Array.fill
Consider using fill
:
Array(9).fill().map(()=>Array(9).fill())
The idea here is that fill()
will fill out the items with undefined
, which is enough to get map
to work on them.
You could also fill directly:
Array(9).fill(Array(9))
Alternatives to Array(9).fill()
include
Array(...Array(9))
[].push(...Array(9))
[].concat(Array(9))
Array.from(Array(9))
We can rewrite the solution a bit more semantically as:
function array9() { return Array(9).fill(); }
array9().map(array9)
or
function array(n) { return Array(n).fill(); }
array(9).map(() => array(9))
Array.from
provides us with an optional second mapping argument, so we have the alternative of writing
Array.from(Array(9), () => Array.from(Array(9));
or, if you prefer
function array9(map) { return Array.from(Array(9), map); }
array9(array9);
For verbose description and examples, see Mozilla's Docs on Array.prototype.fill()
here.
and for Array.from()
, here.
Note that neither Array.prototype.fill()
nor Array.from()
has support in Internet Explorer. A polyfill for IE is available at the above MDN links.
partition(Array(81), 9)
if you have a partition
utility handy. Here's a quick recursive one:
function partition(a, n) {
return a.length ? [a.splice(0, n)].concat(partition(a, n)) : [];
}
We can loop a bit more efficiently with
var a = [], b;
while (a.push(b = []) < 9) while (b.push(null) < 9);
Taking advantage of the fact that push
returns the new array length.
var matrix = [];
for(var i=0; i<9; i++) {
matrix[i] = new Array(9);
}
... or:
var matrix = [];
for(var i=0; i<9; i++) {
matrix[i] = [];
for(var j=0; j<9; j++) {
matrix[i][j] = undefined;
}
}
There is something about Array.fill
I need to mention.
If you just use below method to create a 3x3 matrix.
Array(3).fill(Array(3).fill(0));
You will find that the values in the matrix is a reference.
If you want to pass by value rather than reference, you can leverage Array.map
to create it.
Array(3).fill(null).map(() => Array(3).fill(0));
// initializing depending on i,j:
var M=Array.from({length:9}, (_,i) => Array.from({length:9}, (_,j) => i+'x'+j))
// Print it:
console.table(M)
// M.forEach(r => console.log(r))
document.body.innerHTML = `<pre>${M.map(r => r.join('\t')).join('\n')}</pre>`
// JSON.stringify(M, null, 2) // bad for matrices
Beware that doing this below, is wrong:
// var M=Array(9).fill([]) // since arrays are sparse
// or Array(9).fill(Array(9).fill(0))// initialization
// M[4][4] = 1
// M[3][4] is now 1 too!
Because it creates the same reference of Array 9 times, so modifying an item modifies also items at the same index of other rows (since it's the same reference), so you need an additional call to .slice or .map on the rows to copy them (cf torazaburo's answer which fell in this trap)
note: It may look like this in the future, with Number.range() proposal
const M = [...Number.range(1,10)].map(i => [...Number.range(1,10)].map(j => i+'x'+j))
This is an exact fix to your problem, but I would advise against initializing the matrix with a default value that represents '0' or 'undefined', as Arrays in javascript are just regular objects, so you wind up wasting effort. If you want to default the cells to some meaningful value, then this snippet will work well, but if you want an uninitialized matrix, don't use this version:
/**
* Generates a matrix (ie: 2-D Array) with:
* 'm' columns,
* 'n' rows,
* every cell defaulting to 'd';
*/
function Matrix(m, n, d){
var mat = Array.apply(null, new Array(m)).map(
Array.prototype.valueOf,
Array.apply(null, new Array(n)).map(
function() {
return d;
}
)
);
return mat;
}
Usage:
< Matrix(3,2,'dobon');
> Array [ Array['dobon', 'dobon'], Array['dobon', 'dobon'], Array['dobon', 'dobon'] ]
If you would rather just create an uninitialized 2-D Array, then this will be more efficient than unnecessarily initializing every entry:
/**
* Generates a matrix (ie: 2-D Array) with:
* 'm' columns,
* 'n' rows,
* every cell remains 'undefined';
*/
function Matrix(m, n){
var mat = Array.apply(null, new Array(m)).map(
Array.prototype.valueOf,
new Array(n)
);
return mat;
}
Usage:
< Matrix(3,2);
> Array [ Array[2], Array[2], Array[2] ]
If you really like one-liners and there is a use for underscore.js in your project (which is a great library) you can do write-only things like:
_.range(9).map(function(n) {
return _.range(9).map(function(n) {
return null;
});
});
But I would go with standard for-cycle version mentioned above.
The question is slightly ambiguous, since None
can translate into either undefined
or null
. null
is a better choice:
var a = [], b;
var i, j;
for (i = 0; i < 9; i++) {
for (j = 0, b = []; j < 9; j++) {
b.push(null);
}
a.push(b);
}
If undefined
, you can be sloppy and just don't bother, everything is undefined
anyway. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With