简体   繁体   English

如何轻松创建空矩阵 javascript?

[英]How do you easily create empty matrices javascript?

In python, you can do this:在 python 中,您可以这样做:

[([None] * 9) for x in range(9)]

and you'll get this:你会得到这个:

[[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]]

How can I do the equivalent in javascript?我怎样才能在 javascript 中做同样的事情?

Array.fill

Consider using fill :考虑使用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.这里的想法是fill()将使用undefined填充项目,这足以让map对其进行处理。

You could also fill directly:也可以直接填写:

Array(9).fill(Array(9))

(important note: Array(9).fill(Array(9)) will fill each row of the array with the same array, so changing one row will change the other rows). (重要提示: Array(9).fill(Array(9))将用相同的数组填充数组的每一行,因此更改一行将更改其他行)。

Alternatives to Array(9).fill() include Array(9).fill()的替代品包括

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.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 .有关详细描述和示例,请参阅 Mozilla Array.prototype.fill()文档。
and for Array.from() , here .对于Array.from()在这里

Note that neither Array.prototype.fill() nor Array.from() has support in Internet Explorer.注意Array.prototype.fill()Array.from()在 Internet Explorer 中都不支持。 A polyfill for IE is available at the above MDN links. IE 的 polyfill 可在上述 MDN 链接中找到。

Partitioning分区

partition(Array(81), 9)

if you have a partition utility handy.如果您有一个方便的partition实用程序。 Here's a quick recursive one:这是一个快速递归的:

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

Looping循环播放

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.利用push返回新数组长度的事实。

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.我需要提到一些关于Array.fill的内容。

If you just use below method to create a 3x3 matrix.如果您只是使用以下方法创建一个 3x3 矩阵。

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

You will find that the values in the matrix is a reference.你会发现矩阵中的值是一个参考。

在此处输入图像描述


Optimized solution (prevent passing by reference):优化方案(防止引用传递):

If you want to pass by value rather than reference, you can leverage Array.map to create it.如果你想通过值而不是引用传递,你可以利用Array.map来创建它。

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)因为它创建了 Array 的相同引用 9 次,所以修改一个项目也会修改其他行的相同索引处的项目(因为它是相同的引用),所以您需要在要复制的行上额外调用 .slice 或 .map他们(cf torazaburo 的回答落入了这个陷阱)

note: It may look like this in the future, with Number.range() proposal注意:未来可能看起来像这样,带有Number.range() 提议

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.这是对您的问题的确切解决方法,但我建议不要使用表示“0”或“未定义”的默认值初始化矩阵,因为 javascript 中的数组只是常规对象,因此您最终会浪费精力。 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:如果你真的喜欢单线并且在你的项目中使用underscore.js (这是一个很棒的库),你可以做只写的事情,比如:

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

But I would go with standard for-cycle version mentioned above.但我会选择上面提到的标准循环版本。

For a 2-d matrix I'd do the following对于二维矩阵,我会执行以下操作

var data = Array(9 * 9).fill(0);
var index = (i,j) => 9*i + j;
//any reference to an index, eg. (3,4) can be done as follows
data[index(3,4)]; 

You can replace 9 with any generic ROWS and COLUMNS constants.您可以将9替换为任何通用的 ROWS 和 COLUMNS 常量。

The question is slightly ambiguous, since None can translate into either undefined or null .这个问题有点模棱两可,因为None可以转换为undefinednull null is a better choice: 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);
}

If undefined , you can be sloppy and just don't bother, everything is undefined anyway.如果undefined ,你可能会马虎,只是不要打扰,反正一切都是undefined的。 :) :)

Here's one, no looping:这是一个,没有循环:

(Math.pow(10, 20)+'').replace((/0/g),'1').split('').map(parseFloat);

Fill the '20' for length, use the (optional) regexp for handy transforms and map to ensure datatype.填写“20”作为长度,使用(可选)正则表达式进行方便的转换和映射以确保数据类型。 I added a function to the Array prototype to easily pull the parameters of 'map' into your functions.. bit risky, some people strongly oppose touching native prototypes, but it does come in handy..我在 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))

better.更好的。 that exactly will work.这完全可以。

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;
}


what was shown显示了什么

Array(9).fill(Array(9)); // Not correctly working

It does not work, because all cells are fill with one array它不起作用,因为所有单元格都填充了一个数组

JavaScript doesn't have a built-in 2D array concept, but you can certainly create an array of arrays. JavaScript 没有内置的 2D 数组概念,但您当然可以创建数组数组。

function createMatrix(row, column, isEmpty) {
        let matrix = []
        let array = []
        let rowColumn = row * column
        for (let i = 1; i <= rowColumn; i++) {
            isEmpty ?  array.push([]) :  array.push(i)

            if (i % column === 0) {
                matrix.push(array)
                array = []
            }
        }
        return matrix
    }

createMatrix(5, 3, true)

or或者

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)

Use this function or some like that.使用此功能或类似的功能。 :) :)

function createMatrix(line, col, defaultValue = 0){ 
    return new Array(line).fill(defaultValue).map((x)=>{ return new Array(col).fill(defaultValue); return x; }); 
}
var myMatrix = createMatrix(9,9);

 const dim1 = 9 const dim2 = 9 const init = 0 const matrix = Array.from({length:dim1}, _=>Array(dim2).fill(init))

Well, you can create an empty 1-D array using the explicit Array constructor:好吧,您可以使用显式 Array 构造函数创建一个空的一维数组:

a = new Array(9)

To create an array of arrays, I think that you'll have to write a nested loop as Marc described.要创建一个数组数组,我认为您必须按照 Marc 的描述编写一个嵌套循环。

Coffeescript 来救援!

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

Array.from(new Array(row), () => new Array(col).fill(0));

I'll give it my shot as well我也会给它我的镜头

var c = Array;

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

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

Readable and maintainable !可读可维护!

In python, you can do this:在python中,您可以执行以下操作:

[([None] * 9) for x in range(9)]

and you'll get this:然后您会得到:

[[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]]

How can I do the equivalent in javascript?我该如何在javascript中做等效的事情?

You can add functionality to an Array by extending its prototype object.您可以通过扩展其prototype对象来向 Array 添加功能。

Array.prototype.nullify = function( n ) {
    n = n >>> 0;
    for( var i = 0; i < n; ++i ) {
        this[ i ] = null;
    }
    return this;
};

Then:然后:

var arr = [].nullify(9);

or:或者:

var arr = [].nullify(9).map(function() { return [].nullify(9); });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM