创建三维维度数组

Create 3D dimensional array

本文关键字:数组 三维 创建      更新时间:2023-09-26

在Javascript中,我没有看到任何教程清楚地解释如何创建

MyItems[Row][Index][categories]

因此

MyItems[0][0][0]=1
MyItems[1][0][0]='stock'
MyItems[5][1][0]='pending'

我的用例是每个索引将包含不同的值,即整数或字符串。

在访问没有价值的 MyItems[0][1][0] 时避免出错的最佳方法是什么?

因为 JS 没有实际的多维数组,而只是有嵌套数组,不一定形成矩形结构,所以你需要先检查每个嵌套数组。一个简单的"真实"测试就可以了。

if (myItems[0] && myItems[0][0])
    myItems[0][0].push(1);

如果你想创建不存在的数组,那么你可以这样做:

if (!myItems[0])
    myItems[0] = [];
if (!myItems[0][0])
    myItems[0][0] = [];
myItems[0][0].push(1);

当然,这假设第一级和第二级应该始终是数组,只有第三级才能保存实际值。如果不是这种情况,则需要对其进行调整。

此外,一个函数将是摆脱重复的好主意。

function addNested(outer, idx1, idx2, idx3, value) {
    if (!outer[idx1])
        outer[idx1] = [];
    if (!outer[idx1][idx2])
        outer[idx1][idx2] = [];
    outer[idx1][idx2][idx3] = value;
}
addNested(myItems, 1, 0, 0, 'stock');

这就是您制作 3D 数组的方式,但我建议不要在数组中混合数据类型,这不是一种常见或标准的做法。

// just filler stuff, ignore the body of this function
function getStringOrNumber(row, col, cat) {
  var thing = row * cols * cats + col * cats + cat;
  return Math.random() < .5 ? thing : thing.toString();
}
// something to deal with each value
function doSomething(value) {
  switch (typeof value) {
    case 'string':
      // logic for string type
      break;
    case 'number':
      // logic for number type
      break;
    default:
      // unexpected?
      break;
  }
}
// here's how you make your 3D array
var rows = 10,
    cols = 10,
    cats = 10,
    array3d = new Array(rows),
    i, j, k;
for (i = 0; i < rows; i++) {
  array3d[i] = new Array(cols);
  for (j = 0; j < cols; j++) {
    array3d[i][j] = new Array(cats);
    for (k = 0; k < cats; k++) {
      array3d[i][j][k] = getStringOrNumber(i, j, k);
      doSomething(array3d[i][j][k]);
    }
  }
}

如果要检查 3d 数组上是否存在索引,请尝试如下函数:

function setValue(array3d, row, col, cat, value) {
  if (array3d[row] && array3d[row][col] && array3d[row][col][cat]) {
    array3d[row][col][cat] = value;
  } else {
    throw new RangeError("Indices out of range");
  }
}

如果您在访问任何数组之前以广度优先模式在每个索引处分配每个数组,那么这将无需任何特殊处理即可工作。

但是,正如您正确识别的那样,如果您希望能够访问可能尚未分配的索引,这将不起作用。

实际上,更

具体地说,您可以尝试读取数组长度之外的索引,在这种情况下,您将获得undefined。问题是,如果第一个或第二个深度undefined,则尝试为该undefined值编制索引将失败。

因此,若要防止此错误,必须防止未定义的第一深度或第二深度索引。

执行此操作的最佳方法是编写一个类,该类提供自动处理特殊处理要求的 getter 和 setter。下面是使用原型模式定义的此类的示例:

(function() {
    var Array3D = function() {
        this.data = [];
    };
    Array3D.prototype.get = function(r,c,z) {
        if (this.data.length <= r) return undefined;
        if (this.data[r].length <= c) return undefined;
        return this.data[r][c][z];
    };
    Array3D.prototype.set = function(r,c,z,v) {
        if (this.data.length <= r) this.data[r] = [];
        if (this.data[r].length <= c) this.data[r][c] = [];
        this.data[r][c][z] = v;
        return this;
    };
    window.Array3D = Array3D;
})();
var a = new Array3D();
alert(a.get(0,0,0)); // undefined, no error
a.set(0,0,0,'x');
alert(a.get(0,0,0)); // 'x'
a.set(234,1234,342,'y');
alert(a.get(234,1234,342)); // 'y'
alert(a.get(0,1,0)); // undefined, no error
alert(a.get(12341234,243787,234234)); // undefined, no error

由于这与我的另一个答案完全不同,我认为建议使用嵌套稀疏数组的另一种方法会很有帮助,该方法可以使用关联数组或对象来实现。试试这个:

// N-dimensional array
function ArrayND() {
  // nothing to do here, seriously
}
ArrayND.prototype.setValue = function (value) {
  var indices = arguments,
      nest = this,
      index, i;
  
  // note the range of values since the last recursion is being set to a value
  for (i = 1; i < indices.length - 2; i++) {
    index = indices[i];
    if (nest[index] instanceof ArrayND) {
      nest = nest[index];
    } else if (typeof nest[index] === "undefined") {
      // recursive functionality!
      nest = nest[index] = new ArrayND();
    } else {
      // we don't want to get rid of this value by accident!
      return false;
    }
  }
  
  // now "nest" is equal to the ArrayND you want to set the value inside of
  index = indices[i];
  nest[index] = value;
  // we set the value successfully!
  return true;
}
ArrayND.prototype.getValue = function () {
  var indices = arguments,
      nest = this,
      index, i;
  
  // note the range because we're getting the last value
  for (i = 0; i < indices.length; i++) {
    index = indices[i];
    
    // for last recursion, just has to exist, not be ArrayND
    if (nest[index]) {
      nest = nest[index];
    } else {
      // nothing is defined where you're trying to access
      return undefined;
    }
  }
  
  return nest;
}
var arrayND = new ArrayND();
arrayND.setValue(1, 0, 0, 0);
arrayND.setValue("stock", 1, 0, 0);
arrayND.setValue("pending", 5, 1, 0);
// you can treat it like a normal 3D array if you want
console.log(arrayND[0][0][0]); // 1
console.log(arrayND[1][0][0]); // "stock"
console.log(arrayND[5][1][0]); // "pending"
// or use a nicer way to get the values
console.log(arrayND.getValue(1, 0, 0)); // "stock"
// phew, no errors!
console.log(arrayND.getValue(3, 1, 0)); // undefined
// some awesome recursive functionality!
console.log(arrayND.getValue(5).getValue(1).getValue(0)); // "pending"