我一直在网上阅读,一些地方说这是不可能的,一些地方说这是可能的,然后给出一个例子,另一些地方反驳这个例子,等等。

如何在JavaScript中声明一个2维数组?(假设这是可能的) 我如何访问它的成员?(myArray[0][1] or myArray[0,1]?)


当前回答

最简单的方法:

var arr  = [];

var arr1 = ['00','01'];
var arr2 = ['10','11'];
var arr3 = ['20','21'];

arr.push(arr1);
arr.push(arr2);
arr.push(arr3);

alert(arr[0][1]); // '01'
alert(arr[1][1]); // '11'
alert(arr[2][0]); // '20'

其他回答

数组的行和列的大小只有在运行时才知道,那么下面的方法可以用来创建一个动态的2d数组。

var num = '123456'; 变量行 = 3;运行时已知 var col = 2;运行时已知 是 i = 0; var array2D = [[]]; for(var r = 0; r < row; ++r) { array2D[r] = []; for(var c = 0; c < col; ++c) { array2D[r][c] = num[i++]; } } console.log(array2D); [[ '1', '2' ], [ '3', '4' ], [ '5', '6' ]] console.log(array2D[2][1]);6

ES6+、ES2015+可以用更简单的方式做到这一点


创建3 × 2的数组,填充为true

[...Array(3)].map(item => Array(2).fill(true))

创建一个非稀疏的“2D”数组(x,y),所有的索引都是可寻址的,并且值设置为空:

let 2Darray = new Array(x).fill(null).map(item =>(new Array(y).fill(null))) 

“3D”数组(x,y,z)

let 3Darray = new Array(x).fill(null).map(item=>(new Array(y).fill(null)).map(item=>Array(z).fill(null)))

关于这个问题的变化和更正已经在评论中提到,并在不同的地方回应了这个问题,但不是一个实际的答案,所以我在这里添加了它。

应该注意的是(类似于大多数其他答案),这有O(x*y)时间复杂度,所以它可能不适合非常大的数组。

这将构造任何维度的数组。

function makeArrayChildren(parent, firstDimension, ...dimensions) {
  for (let i = 0; i < parent.length; i++) {
    parent[i] = new Array(firstDimension);
    if (dimensions.length != 0) {
      makeArrayChildren(parent[i], ...dimensions);
    }
  }
}
function makeArray(firstDimension, ...dimensions) {
  if (firstDimension == undefined) {
    throw Exception("Too few dimensions");
  }
  let topArray = new Array(firstDimension);
  if (dimensions.length != 0) makeArrayChildren(topArray, ...dimensions);
  return topArray;
}

这里还有另外两个我想做的函数,我可以用它作为一个完整性检查:一个用于在多维数组中所有最低级别项上执行的每个函数,一个填充方法。

Array.prototype.dimensionalFill = function (value) {
  for (let i = 0; i < this.length; i++) {
    const elem = this[i];
    if (elem instanceof Array) {
      elem.dimensionalFill(value);
    } else {
      this[i] = value;
    }
  }
};
/*Unlike forEach, this also loops over undefined values. */
Array.prototype.dimensionalForEach = function (callableFunc, thisArg) {
  if (thisArg != undefined) {
    return this.dimensionalForEach(callableFunc.bind(thisArg));
  }
  for (let i = 0; i < this.length; i++) {
    const elem = this[i];
    if (elem instanceof Array) {
      elem.dimensionalForEach(callableFunc);
    } else {
      callableFunc(elem, i, this);
    }
  }
};

这里有一个漂亮的小检查,它使用了所有的特性。所以至少,它不可能完全错误。

let arr = makeArray(10, 10, 5, 4);
arr.dimensionalFill(2);
let sum = 0;
arr.dimensionalForEach((elem) => {
  sum += elem;
});
console.log(`sum: ${sum} === ${10 * 10 * 5 * 4 * 2}`);

值得一提的是,在这一点上,创建一个全新的结构将是一个更好的实践,但这很有趣。

性能

今天2020.02.05,我在Chrome v79.0, Safari v13.0.4和Firefox v72.0上对MacOs HighSierra 10.13.6进行测试,以选择解决方案。

非初始化二维数组的结论

深奥的解{}/arr[[i,j]] (N)对于大小数组都是最快的,看起来对于大型稀疏数组也是不错的选择 基于for-[]/while (A,G)的求解速度较快,是小型数组的良好选择。 -[] (B,C)的解是快速的,对于大数组是很好的选择 基于Array..map/from/fill (I,J,K,L,M)对于小数组来说非常慢,而对于大数组来说非常快 for- array (n) (B,C)在safari上比for-[] (A)慢得多 令人惊讶的是,for-[] (A) for大数组在所有浏览器上都很慢 解决方案K对于所有浏览器的小数组都很慢 解决方案A,E,G对于所有浏览器的大数组都很慢 对于所有浏览器上的所有数组,解决方案M是最慢的

初始化二维数组的结论

基于for/while (A,B,C,D,E,G)的解决方案对于所有浏览器上的小数组来说都是最快的/相当快的 基于for (A,B,C,E)的解决方案对于大数组在所有浏览器上都是最快的/相当快的 基于Array..map/from/fill (I,J,K,L,M)在所有浏览器上都是中、快或慢的小数组 针对大数组的F,G,H,I,J,K,L解决方案在chrome和safari上中等或快速,但在firefox上最慢。 深奥的解决方案{}/arr[[i,j]] (N)对于所有浏览器上的大小数组都是最慢的

细节

测试没有填充(初始化)输出数组的解决方案

我们测试解的速度

小数组(12个元素)-你可以在你的机器上执行测试 大数组(100万个元素)数组-你可以在你的机器上执行测试

函数A(r) { Var arr = []; For (var I = 0;I < r;I ++) arr[I] = []; 返回arr; } 函数B(r, c) { var arr = new Array(r); For (var I = 0;I < arrr .length;i++) arr[i] = new Array(c); 返回arr; } 函数C(r, C) { var arr =数组(r); For (var I = 0;I < arrr .length;i++) arr[i] =数组(c); 返回arr; } 函数D(r, c) { //奇怪,但有效 Var arr = []; For (var I = 0;I < r;我+ +){ arr.push ([]); 加勒比海盗[我].push(数组(c)); } 返回arr; } 函数E(r, c) { Let array = [[]]; For (var x = 0;X < c;x + +) { 数组[x] = []; For (var y = 0;Y < r;数组[x][Y] = [0]; } 返回数组; } 函数F(r, c) { var makeArray = function(调暗,arr) { If (dims[1] === undefined) { 返回数组(dim [0]); } arr = Array(dimms [0]); For (var I = 0;I < dim [0];我+ +){ arr[i] = Array(dimms [1]); arr[i] = makeArray(dms .slice(1), arr[i]); } 返回arr; } 返回makeArray([r, c]); } 函数G(r) { Var a = []; While (a.push([]) < r); 返回一个; } 函数H(r,c) { 函数createArray(length) { var arr =新的数组(长度|| 0), I =长度; 如果参数。长度> 1){ var args = Array.prototype.slice。调用(参数,1); while(i——)arr[length-1 - i] = createArray。应用(这个,args); } 返回arr; } 返回createArray (r、c); } 函数I(r, c) { 返回数组(r)[…]。map(x =>数组(c)); } 函数J(r, c) { 返回Array(r).fill(0).map(() => Array(c)); } 函数K(r, c) { return Array.from(Array(r), () => Array(c)); } 函数L(r, c) { 返回Array.from({length: r})。map(e => Array(c)); } 函数M(r, c) { 返回Array.from({长度:r}, () = > Array.from({长度:c }, () => {})); } 函数N(r, c) { 返回{} } // ----------------------------------------------- / /显示 // ----------------------------------------------- Log = (t, f) => { 令A = f(3,4);//创建3行4列的数组 A[1][2] = 6 //第2行第3列设置为6 console.log(“$ {t}[1][2]: ${一个[1][2]},完整:$ {JSON.stringify (A) .replace(/空/ g,“x”)}”); } Log2 = (t, f) => { 令A = f(3,4);//创建3行4列的数组 A[[1,2]] = 6 //第2行第3列设为6 console.log(“$ {t}[1][2]: ${一个[[1,2]]},完整:$ {JSON.stringify (A) .replace(/空/ g,“x”)}”); } 日志(' A '); 日志(B, B); 日志(C, C); 日志(' D ' D); 日志(E, E); 日志(F, F); 日志(G, G); 日志(H, H); 日志(“我”,我); 日志(“J”,J); 日志(K, K); 日志(L, L); 日志(“M”,M); log2 (N, N); 这是解决方案的展示,而不是基准测试

测试填充(初始化)输出数组的解决方案

我们测试解的速度

小数组(12个元素)-你可以在你的机器上执行测试 大数组(100万个元素)数组-你可以在你的机器上执行测试

函数A(r, c, def) { Var arr = []; For (var I = 0;I < r;i++) arr[i] =数组(c).fill(def); 返回arr; } 函数B(r, c, def) { var arr = new Array(r); For (var I = 0;I < arrr .length;i++) arr[i] = new Array(c).fill(def); 返回arr; } 函数C(r, C, def) { var arr =数组(r); For (var I = 0;I < arrr .length;i++) arr[i] =数组(c).fill(def); 返回arr; } 函数D(r, c, def) { //奇怪,但有效 Var arr = []; For (var I = 0;I < r;我+ +){ arr.push ([]); 加勒比海盗[我].push(数组(c)); } For (var I = 0;I < r;i++) for (var j = 0;J < c;j + +) arr[我][j] = def 返回arr; } 函数E(r, c, def) { Let array = [[]]; For (var x = 0;X < c;x + +) { 数组[x] = []; For (var y = 0;Y < r;数组[x][Y] = def; } 返回数组; } 函数F(r, c, def) { var makeArray = function(调暗,arr) { If (dims[1] === undefined) { 返回数组(退去[0]).fill (def); } arr = Array(dimms [0]); For (var I = 0;I < dim [0];我+ +){ arr[i] = Array(dimms [1]); arr[i] = makeArray(dms .slice(1), arr[i]); } 返回arr; } 返回makeArray([r, c]); } 函数G(r, c, def) { Var a = []; while (a.push(Array(c).fill(def)) < r); 返回一个; } 函数H(r,c, def) { 函数createArray(length) { var arr =新的数组(长度|| 0), I =长度; 如果参数。长度> 1){ var args = Array.prototype.slice。调用(参数,1); while(i——)arr[length-1 - i] = createArray。应用(这个,args) .fill (def); } 返回arr; } 返回createArray (r、c); } 函数I(r, c, def) { 返回数组(r)[…]。map(x =>数组(c).fill(def)); } 函数J(r, c, def) { 返回数组(r) .fill (0) . map(() = >数组(c) .fill (def)); } 函数K(r, c, def) { 返回Array.from(Array(r), () => Array(c).fill(def)); } 函数L(r, c, def) { 返回Array.from({length: r})。map(e => Array(c).fill(def)); } 函数M(r, c, def) { 返回Array.from({长度:r}, () = > Array.from({长度:c}, () = > def)); } 函数N(r, c, def) { 让arr = {}; For (var I = 0;I < r;i++) for (var j = 0;J < c;j + +) arr [[i, j]] = def; 返回arr; } // ----------------------------------------------- / /显示 // ----------------------------------------------- Log = (t, f) => { 令A = f(1000,1000,7);//创建一个1000行1000列的数组 //每个数组单元格初始化为7 A[800][900] = 5 //第800行和第901列设为5 console.log(“$ {t}[1][2]: ${一个[1][2]},{t}美元[800][901]:${一个[800][900]}”); } Log2 = (t, f) => { 令A = f(1000,1000,7);//创建一个1000行1000列的数组 //每个数组单元格初始化为7 A[[800,900]] = 5 //第800行第900列设置为5 console.log(“$ {t}[1][2]: ${一个[[1,2]]},{t}美元[800][900]:${一个[[800900]]}'); } 日志(' A '); 日志(B, B); 日志(C, C); 日志(' D ' D); 日志(E, E); 日志(F, F); 日志(G, G); 日志(H, H); 日志(“我”,我); 日志(“J”,J); 日志(K, K); 日志(L, L); 日志(“M”,M); log2 (N, N); 这是解决方案的展示,而不是基准测试