创建3D维数组

时间:2015-03-08 19:46:56

标签: javascript

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

MyItems[Row][Index][categories]

这样

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

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

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

4 个答案:

答案 0 :(得分:4)

因为JS不具有实际的多维数组,而只是具有不必形成矩形结构的嵌套数组,所以您需要首先检查每个嵌套数组。一个简单的" truthy"测试没问题。

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');

答案 1 :(得分:1)

这就是你制作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");
  }
}

答案 2 :(得分:0)

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

但是,正如您已经正确认识的那样,如果您希望能够访问尚未分配的索引,那么这将无法正常工作。

实际上,更具体地说, 允许您尝试读取数组长度以外的索引,在这种情况下,您将获得undefined。问题是,如果第一个或第二个深度得到undefined,则尝试索引undefined值将失败。

因此,为防止出现此错误,您必须防范未定义的第一或第二深度索引。

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

&#13;
&#13;
(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
&#13;
&#13;
&#13;

答案 3 :(得分:0)

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

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