你如何轻松创建空矩阵javascript?

问题描述 投票:39回答:14

在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中执行等效操作?

javascript
14个回答
57
投票
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;
    }
}

0
投票

更好。这确实会奏效。

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

它不起作用,因为所有单元格都填充了一个数组


0
投票

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)

-1
投票

那么,您可以使用显式Array构造函数创建一个空的1-D数组:

a = new Array(9)

要创建一个数组数组,我认为你必须像Marc描述的那样编写一个嵌套循环。


-1
投票

您可以通过扩展其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); });

-1
投票

我也会试一试

var c = Array;

for( var i = 0, a = c(9); i < 9; a[i] = c(9), i++ );

console.log( a.join(",") );
//",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"

可读和可维护!


59
投票

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。

Partitioning

partition(Array(81), 9)

如果你有一个partition实用程序方便。这是一个快速递归的:

function partition(a, n) {
  return a.length ? [a.splice(0, n)].concat(partition(a, n)) : [];
}  

Looping

我们可以更有效地循环

var a = [], b;
while (a.push(b = []) < 9) while (b.push(null) < 9);

利用push返回新数组长度的事实。


10
投票

// 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))

4
投票

如果你真的喜欢单行,并且在你的项目中使用underscore.js(这是一个很棒的库),你可以做只写的事情:

_.range(9).map(function(n) {
      return _.range(9).map(function(n) {
            return null;
      });
});

但我会选择上面提到的标准for-cycle版本。


4
投票

我需要提一下Array.fill

如果您只是使用以下方法来创建3x3矩阵。

Array(3).fill(Array(3).fill(0));

您会发现矩阵中的值是参考。

enter image description here


优化的解决方案(防止通过引用传递):

如果你想通过值而不是引用传递,你可以利用Array.map来创建它。

Array(3).fill(null).map(() => Array(3).fill(0));

enter image description here


3
投票

这是对你的问题的一个确切修复,但我建议不要使用表示'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] ]

1
投票

这个问题有点含糊不清,因为None可以翻译成undefinednullnull是一个更好的选择:

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。 :)


0
投票

Coffeescript救援!

[1..9].map -> [1..9].map -> null


0
投票

这是一个,没有循环:

(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))
© www.soinside.com 2019 - 2024. All rights reserved.