【问题标题】:JS flat object as matrix coords : how to init all values?JS 平面对象作为矩阵坐标:如何初始化所有值?
【发布时间】:2016-05-19 09:41:15
【问题描述】:

这是我的代码:

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

我的问题是:如何实现 init() 函数,什么时候可以用任何等级构建 ArrayND?

例子:

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 维数组坐标的平面对象。

【问题讨论】:

    标签: javascript object matrix initialization coordinates


    【解决方案1】:

    如果我理解正确,您始终可以生成您的 N 维数组并将其初始化如下。最后一个参数是初始化值。前一个是维度数组,它的长度是维度的数量,项目是要创建的数组的每个维度的大小。

    要实例化多维数组,我们必须有一个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() 做同样的事情,但为了抽象,我更喜欢从右到左

    【讨论】:

    • 顺便说一句,您现在可以使用 console.log。恭喜 1k :)
    • @Nina Scholz:嘿,谢谢你们... console.log 如果大大松了一口气。
    • 只是一个小提示,可以省略stringify。
    • 谢谢我像 console.log(m) 一样尝试过,但它不像 JSON.stringify 那样显示。只显示底层,上面的级别就像简报一样。但无论如何摆脱这个 document.write 事情真的是很大的解脱。
    • 这是一个非常好的 n 维数组实现,但这不是我想要的,我想要一个包含 n 维数组坐标的平面对象。我将编辑我的问题以使其更清楚。
    【解决方案2】:

    如果您想为每个 'x,y' 属性使用 defaultValue 填充自定义对象,并使用 [x, y] 检索值,您可以这样做:

    init ( defaultValue ) {
        for ( var x = 0; x < this._ranks[ 0 ]; x += 1 ) {
            for ( var y = 0; y < this._ranks[ 1 ]; y += 1 ) {
                this.coords[ String( x ) + ',' + String( y ) ] = defaultValue;
            }
        }
    }
    

    并使用如下吸气剂:

    get valueAt( _coords ) {
        return this.coords[ _coords.join( ',' ) ];
    }
    

    【讨论】:

    • 是的,但这仅适用于等级为 2 的 ArrayND。我的问题是,如何使用等级 n ​​来做到这一点(n 可能是无限的)。这将产生一个“无限”数量的 for 循环。可以动态创建 for 循环,还是可以使用递归? ...例如,如果我有“x,y,z”属性,或者只有“x”,那么您的代码将不再工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多