3

If a=[[1,[],"f",3],[3,[4,"x"]]] and b=[1,1].

I want to read a by b like a[1][1] to get [4,"x"]. Note that b is an array which should only consist of integers.

You could also do eval('a['+b.join('],[')+']') but requires the actual variable name as string and it's ugly.

Here are some of my functions:

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

This could be useful for reading a nested array in an imperative way in this example:

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

Is there any better way to do this? Are there native functions for this?

  • 1
    Protip: Don't change `Array`'s prototype. It will give you more headaches than usefulness. – Derek 朕會功夫 Aug 20 '16 at 16:26
  • @Derek朕會功夫 Give me some examples. – Anastasia Dunbar Aug 20 '16 at 16:28
  • 1
    [*Why is extending native objects a bad practice?*](https://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice) Many libraries in the last decade have tried to modify builtin object's prototype, and they all failed miserably. The general principle is that you only change what you own, and leave objects that you don't own untouched. – Derek 朕會功夫 Aug 20 '16 at 16:35

2 Answers2

3

You could use Array#reduce for it.

You start with the whole array and return for every element of b a part of the array until all indices are used.

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; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • With ES6, you are able to make it neater with `const result = b.reduce((v, i) => v[i], a)` – bitten Aug 20 '16 at 16:14
  • Thank you, can I change the element inside of `[4,"x"]`? – Anastasia Dunbar Aug 20 '16 at 16:16
  • yes, you can, because you get the reference to the array. please see second example. – Nina Scholz Aug 20 '16 at 16:18
  • If I had to like set that array into an another element as `result=["test"]` how would I do that? – Anastasia Dunbar Aug 20 '16 at 16:48
  • 1
    you could use [`Array#splice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice), for keeping the reference and delete all elements inside and move the new content to the reference. please see edit in the second example. – Nina Scholz Aug 20 '16 at 17:03
0

I had written a reusable generic code exactly for this purpose to get the nested object properties dynamically. Actually i was targeting objects but since in JS an array is a perfect object it also applies for arrays too. So lets see how it works in this particular case;

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)
Redu
  • 25,060
  • 6
  • 56
  • 76