在Javascript中,我没有看到任何教程清楚地解释如何创建
MyItems[Row][Index][categories]
这样
MyItems[0][0][0]=1
MyItems[1][0][0]='stock'
MyItems[5][1][0]='pending'
我的用例是每个索引都包含不同的值,即整数或字符串。
访问没有值的MyItems [0] [1] [0]时避免错误的最佳方法是什么?
答案 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的类,该类自动处理特殊处理要求。以下是使用原型模式定义的类的示例:
(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;
答案 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"