在Javascript中使用数组读取另一个数组?

3
如果a = [[1,[],"f",3],[3,[4,"x"]]]b=[1,1]
我希望通过 b 来访问 a,例如 a[1][1],得到结果 [4,"x"]。请注意,b 是一个只包含整数的数组。
你也可以使用eval('a['+b.join('],[')+']'),但需要实际变量名作为字符串,而且这种写法很丑陋。
以下是我的一些函数:
Array.prototype.readByArray = function(a) {
    var c = this;
    for (var i = 0; i < a.length; i++) {
        c = c[a[i]];
    }
    return c;
};
Array.prototype.emptyByArray = function(a) {
    var c = this.readByArray(a);
    c.splice(0, c.length);
};
Array.prototype.concateByArray = function(a, e) {
    var c = this.readByArray(a);
    for (var i = 0; i < e.length; i++) {
        c.push(e[i]);
    }
};
Array.prototype.setByArray = function(a, e) {
    this.emptyByArray(a);
    this.readByArray(a).push(e);
};

这在以下示例中以命令方式读取嵌套数组时可能很有用:
Array.prototype.readByArray=function(a){var c=this;for(var i=0;i<a.length;i++){c=c[a[i]];}return c;};
var a = [1,2,3,[1,2,3,[{x: 3},"test"],4],"foo","bar"]; //Your array
var b = [0]; //Reading stack
var s = '[\n'; //Output
while(b[0]<a.length){
    if(Array.isArray(a.readByArray(b))){
        s+=' '.repeat(b.length)+'[\n';
        b.push(-1);
    }else{
        s+=' '.repeat(b.length)+JSON.stringify(a.readByArray(b))+'\n';
    }
    b[b.length-1]++;
    while(b[b.length-1]>=a.readByArray(b.slice(0,-1)).length){
        b.pop();
        b[b.length-1]++;
        s+=' '.repeat(b.length)+']\n';
    }
}
console.log(s);

有没有更好的方法来做这件事?是否有原生函数可用?


1
专业提示:不要更改Array的原型。这样做会给你带来更多的麻烦而不是好处。 - Derek 朕會功夫
@Derek,请给我一些例子。 - Anastasia Dunbar
1
为什么扩展原生对象是一种不好的做法?过去十年中,许多库都试图修改内置对象的原型,但它们都失败了。一般的原则是只更改你拥有的内容,而将你不拥有的对象保持不变。 - Derek 朕會功夫
2个回答

3
你可以使用 Array#reduce 来实现。
你需要从整个数组开始,对于 b 的每个元素,返回数组的一部分,直到使用完所有索引。

var a = [[1, [], "f", 3], [3, [4, "x"]]],
    b = [1, 1],
    result = b.reduce(function (v, i) {
        return v[i];
    }, a);
    
console.log(result);

ES6

var a = [[1, [], "f", 3], [3, [4, "x"]]],
    b = [1, 1],
    result = b.reduce((v, i) => v[i], a);
    
console.log(result);
result[0] = 42;
console.log(a);
result.splice(0, result.length, 'test');
console.log(a);
.as-console-wrapper { max-height: 100% !important; top: 0; }


使用ES6,你可以通过 const result = b.reduce((v, i) => v[i], a) 使代码变得更加简洁。 - bitten
谢谢,我可以更改[4,“x”]内的元素吗? - Anastasia Dunbar
可以的,因为你得到了数组的引用。请看第二个例子。 - Nina Scholz
如果我想将该数组设置为另一个元素,例如 result=["test"],我该如何做? - Anastasia Dunbar
1
你可以使用 Array#splice 来保留引用、删除所有元素并将新内容移动到引用中。请参见第二个示例中的编辑。 - Nina Scholz

0

我已经编写了一个可重用的通用代码,专门用于动态获取嵌套对象属性。实际上,我是针对对象进行定位的,但由于在JS中数组是一个完美的对象,因此它也适用于数组。因此,让我们看看它在这种特殊情况下如何工作;

Object.prototype.getNestedValue = function(...a) {
  return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};

var a = [[1,[],"f",3],[3,[4,"x"]]],
    b = [1,1],
    c = a.getNestedValue(...b);
console.log(c)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接