这是我的代码:
class ArrayND {
/**
* @param {Array<number>} ranks
*/
constructor (ranks) {
this.coords = {}
this._ranks = ranks
}
/**
* @param {number|string} defaultValue
*/
init (defaultValue) {
// How to init this.coords with defaultValue given this._ranks ?
}
}
我想要实现的目标:
const myArrayND = new ArrayND([3, 2])
myArrayND.init(5)
/*
myArrayND.coords should be :
{
0,0: 5,
0,1: 5,
1,0: 5,
1,1: 5,
2,0: 5,
2,1: 5
}
*/
myArrayND.coords[[2, 1]] // returns 5
我的问题是:当 ArrayND 可以用任意等级构建时,如何实现 init() 函数?
示例:
const firstArray = new ArrayND([])
firstArray.init(5)
// firstArray.coords contains {}
const secondArray = new ArrayND([5])
secondArray.init('aze')
/* secondArray.coords contains {
0: 'aze',
1: 'aze',
2: 'aze',
3: 'aze',
4: 'aze',
} */
const thirdArray = new ArrayND([2, 3])
thirdArray.init(2)
/* thirdArray.coords contains {
0,0: 2,
0,1: 2,
0,2: 2,
1,0: 2,
1,1: 2,
1,2: 2,
} */
const anotherExample = new ArrayND([1, 2, 3])
anotherExample.init(1)
/* anotherExample.coords contains {
0,0,0: 1,
0,0,1: 1,
0,0,2: 1,
0,1,0: 1,
0,1,1: 1,
0,1,2: 1,
} */
...
我不希望 myObject.coords 包含多维数组,因为我在访问和设置多维数组中的值时遇到其他问题:请参阅 JS multidimentional array modify value 。它工作得很好,但丑陋的开关盒非常令人厌恶。
而不是拥有
multiDimArray = [
[
[1],
[2],
[3]
],
[
[4],
[5],
[6]
]
]
multiDimArray[0][1][2] // returns 6
问题在于访问:
function setValue(indexArray, value) {
switch (indexArray.length) {
case 0:
multiDimArray = value
case 1:
multiDimArray[indexArray[0]] = value
case 2:
multiDimArray[indexArray[0]][indexArray[1]] = value
case 3:
multiDimArray[indexArray[0]][indexArray[1]][indexArrat[2]] =value
...
// Very ugly and isn't truly dynamic
}
}
我要
multiDimArray = {
0,0,0: 1,
0,0,1: 2,
0,0,2: 3,
0,1,0: 4,
0,1,1: 5,
0,1,2: 6,
}
multiDimArray[[0, 1, 2]] // returns 6
这样我就可以使用这样的函数动态访问和设置值:(在数组数组的情况下,这是用一个丑陋的开关案例完成的)
function setValue(indexArray, value) {
multiDimArray[indexArray] = value
// much better than before.
}
所以我知道“ArrayND”这个名字可能有点误导,但它实际上不是一个数组,它是一个包含 n 维数组坐标的平面对象。
最佳答案
如果我理解正确,您始终可以生成 N 维数组并将其初始化如下。最后一个参数是初始化值。前面是dimens数组,其长度是维度数,items是要创建的数组每个维度的大小。
要实例化多维数组,我们必须有一个 Array.prototype.clone() 方法,以防止引用被复制。所以事情是这样的。
Object.prototype.getNestedValue = function(...a) {
return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};
Array.prototype.clone = function(){
return this.reduce((p,c,i) => (p[i] = Array.isArray(c) ? c.clone() : c, p),[])
}
function arrayND(...n){
return n.reduceRight((p,c) => c = (new Array(c)).fill(true).map(e => Array.isArray(p) ? p.clone() : p ));
}
var m = arrayND(...[3,4,2,3],5);
m[0][2][1][2] = "five";
console.log(JSON.stringify(m,null,2));
console.log(m.getNestedValue(2,3,1,2));
你当然可以对 Array.prototype.reduce() 做同样的事情,但为了抽象,我更喜欢从右到左
关于javascript - JS 平面对象作为矩阵坐标 : how to init all values?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37319416/