在python中,你可以这样做:
[([None] * 9) for x in range(9)]
你会得到这个:
[[None, None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None, None],
[None, None, None, None, None, None, None, None, None]]
如何在javascript中执行等效操作?
var matrix = [];
for(var i=0; i<9; i++) {
matrix[i] = new Array(9);
}
... 要么:
var matrix = [];
for(var i=0; i<9; i++) {
matrix[i] = [];
for(var j=0; j<9; j++) {
matrix[i][j] = undefined;
}
}
更好。这确实会奏效。
let mx = Matrix(9, 9);
function Matrix(w, h){
let mx = Array(w);
for(let i of mx.keys())
mx[i] = Array(h);
return mx;
}
显示的是什么
Array(9).fill(Array(9)); // Not correctly working
它不起作用,因为所有单元格都填充了一个数组
JavaScript没有内置的2D数组概念,但您当然可以创建一个数组数组。
function createMatrix(row, column, isEmpty) {
let tmpMatrix = []
let tmpArray = []
let rowColumn = row * column
for (let i = 1; i <= rowColumn; i++) {
isEmpty ? tmpArray.push('none') : tmpArray.push(i)
if (i % column === 0) {
tmpMatrix.push(tmpArray)
tmpArray = []
}
}
return tmpMatrix
}
createMatrix(5, 3, true)
要么
function createMatrix(row, column, from) {
let [matrix, array] = [[], []],
total = row * column
for (let element = from || 1; element <= total; element++) {
array.push(element)
if (element % column === 0) {
matrix.push(array)
array = []
}
}
return matrix
}
createMatrix(5, 6, 1)
那么,您可以使用显式Array构造函数创建一个空的1-D数组:
a = new Array(9)
要创建一个数组数组,我认为你必须像Marc描述的那样编写一个嵌套循环。
您可以通过扩展其prototype
对象来向Array添加功能。
Array.prototype.nullify = function( n ) {
n = n >>> 0;
for( var i = 0; i < n; ++i ) {
this[ i ] = null;
}
return this;
};
然后:
var arr = [].nullify(9);
要么:
var arr = [].nullify(9).map(function() { return [].nullify(9); });
我也会试一试
var c = Array;
for( var i = 0, a = c(9); i < 9; a[i] = c(9), i++ );
console.log( a.join(",") );
//",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"
可读和可维护!
Array.fill
考虑使用fill
:
Array(9).fill().map(()=>Array(9).fill())
这里的想法是fill()
将用undefined
填写项目,这足以让map
对它们进行处理。
你也可以直接填写:
Array(9).fill(Array(9))
Array(9).fill()
的替代方案包括
Array(...Array(9))
[].push(...Array(9))
[].concat(Array(9))
Array.from(Array(9))
我们可以在语义上重写解决方案:
function array9() { return Array(9).fill(); }
array9().map(array9)
要么
function array(n) { return Array(n).fill(); }
array(9).map(() => array(9))
Array.from
为我们提供了可选的第二个映射参数,因此我们可以选择写作
Array.from(Array(9), () => Array.from(Array(9));
或者,如果您愿意
function array9(map) { return Array.from(Array(9), map); }
array9(array9);
有关详细说明和示例,请参阅有关Array.prototype.fill()
here的Mozilla文档。
而对于Array.from()
,here。
请注意,Array.prototype.fill()
和Array.from()
都不支持Internet Explorer。上述MDN链接提供了IE的polyfill。
partition(Array(81), 9)
如果你有一个partition
实用程序方便。这是一个快速递归的:
function partition(a, n) {
return a.length ? [a.splice(0, n)].concat(partition(a, n)) : [];
}
我们可以更有效地循环
var a = [], b;
while (a.push(b = []) < 9) while (b.push(null) < 9);
利用push
返回新数组长度的事实。
// 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
注意下面这样做是错误的:
// 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!
因为它创建了相同的数组引用次数9次,所以修改项目也会修改其他行的相同索引处的项目(因为它是相同的引用),因此您需要在要复制的行上另外调用.slice或.map他们(参见torazaburo在这个陷阱中失败的答案)
注意:将来可能看起来像slice-notation-literal proposal (stage 1)
const M = [...1:10].map(i => [...1:10].map(j => i+'x'+j))
如果你真的喜欢单行,并且在你的项目中使用underscore.js(这是一个很棒的库),你可以做只写的事情:
_.range(9).map(function(n) {
return _.range(9).map(function(n) {
return null;
});
});
但我会选择上面提到的标准for-cycle版本。
这是对你的问题的一个确切修复,但我建议不要使用表示'0'或'undefined'的默认值来初始化矩阵,因为javascript中的数组只是常规对象,所以你最终会浪费精力。如果要将单元格默认为某个有意义的值,则此代码段将正常工作,但如果您需要未初始化的矩阵,请不要使用此版本:
/**
* 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;
}
用法:
< Matrix(3,2,'dobon');
> Array [ Array['dobon', 'dobon'], Array['dobon', 'dobon'], Array['dobon', 'dobon'] ]
如果您只想创建一个未初始化的二维数组,那么这比不必要地初始化每个条目更有效:
/**
* 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;
}
用法:
< Matrix(3,2);
> Array [ Array[2], Array[2], Array[2] ]
这个问题有点含糊不清,因为None
可以翻译成undefined
或null
。 null
是一个更好的选择:
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);
}
如果undefined
,你可以马虎而且不要打扰,无论如何一切都是undefined
。 :)
Coffeescript救援!
[1..9].map -> [1..9].map -> null
这是一个,没有循环:
(Math.pow(10, 20)+'').replace((/0/g),'1').split('').map(parseFloat);
填充'20'表示长度,使用(可选)regexp进行方便的转换并映射以确保数据类型。我在Array原型中添加了一个函数,可以轻松地将'map'的参数拉到你的函数中..有点冒险,有些人强烈反对触摸原生原型,但它确实派上用场..
Array.prototype.$args = function(idx) {
idx || (idx = 0);
return function() {
return arguments.length > idx ? arguments[idx] : null;
};
};
// Keys
(Math.pow(10, 20)+'').replace((/0/g),'1').split('').map(this.$args(1));
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
// Matrix
(Math.pow(10, 9)+'').replace((/0/g),'1').split('').map(this.$args(1)).map(this.$args(2))