2

If I have array:

var arr = [
 {
  text: "something",
  child: [
   {
    text: "something child",
    child: [..]
   },..
  ]
 },..
];

Is ther any more efficient way exept rebuilding whole array with updated value by using for() to edit element when I have array of indexes:

var index = [0, 0];

to do this:

arr[0]["child"][0]["text"] = "updated value";

This is just small example but arr will be sometimes 1 level depth sometimes 12, etc. And value I need to update sometimes is in first level:

arr[0]["text"] = "updated value"
user86168
  • 35
  • 2
  • 10
  • Your first example shows you *replacing* a `child`, while the second shows you reassigning the `.text` property of a child? Are both possibilities? – CertainPerformance Aug 13 '18 at 20:50
  • Your data structure looks like a tree, you should look into [Tree Traversal](https://en.wikipedia.org/wiki/Tree_traversal) algorithms and probably figure out what's best for you case – Luiz Chagas Jr Aug 13 '18 at 20:52
  • @CertainPerformance sorry my bad – user86168 Aug 13 '18 at 20:53
  • Efficient how? Speed? Memory? Lines of code? Also, what are the rules to go from `[0,0]` to `arr[0]["child"][0]["text"]`? For instance, if you get `[0,0,0]` is it a "child" property accessor between each index? – Heretic Monkey Aug 13 '18 at 20:55
  • Also, this question's answers have many ways of doing what you want: https://stackoverflow.com/q/11922383/215552 – Heretic Monkey Aug 13 '18 at 20:57
  • @HereticMonkey every number in index array is array index. Rules is first goes just arr[index[0]], then for folowing ones will go ["child"][index[n]] – user86168 Aug 13 '18 at 21:01

4 Answers4

2

You could iterate the indices and update text property at the end.

function update(child, indices, value) {
    indices.reduce((o, i) => o.child[i], { child }).text = value;
}

var array = [{ text: "something", child: [{ text: "something child", child: [] }] }];

update(array, [0, 0], 'foo');

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

You are probably going to want a recursive method that accepts the array, the indexes, and the new value as input. If the index array is of length one, then it updates that element in the array. If it is not, then it calls the method using the child array at the element specified by the first element in the index array, the index array with its first element removed, and the new value.

Zachary Oldham
  • 838
  • 1
  • 5
  • 21
0

A good alternative is using vanilla for-loop.

let arr = [ {  text: "something",  child: [   {    text: "something child",    child: []   }  ] }],
    index = [0, 0],
    current = undefined;

for(let i = 0; i < index.length; i++) {
  if (i === index.length - 1) current[index[i]].text = "Ele from Stack";
  else current = (current || arr)[index[i]].child;
}

console.log(arr);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ele
  • 33,468
  • 7
  • 37
  • 75
0

In my opinion, this in quite unmaintainable and you should consider different data structure. However, you asked about this kind of solution. You can you eval(), which is quite working, even it is dangerous for production environment without additional security checks:

var arr = [{
    text: "something",
    child: [{
            text: "something child",
            child: [{
                text: "something child",
                child: [{
                    text: "something child",
                    child: []
                }]
            }, {
                text: "something child",
                child: []
            }]
        },
        {
            text: "something child",
            child: [{
                text: "something child",
                child: []
            }, {
                text: "something child",
                child: []
            }]
        }
    ]
}, {
    text: "something",
    child: [{
            text: "something child",
            child: [{
                text: "something child",
                child: [{
                    text: "something child",
                    child: []
                }]
            }, {
                text: "something child",
                child: []
            }]
        },
        {
            text: "something child",
            child: [{
                text: "something child",
                child: []
            }, {
                text: "something child",
                child: []
            }]
        }
    ]
}];
var ind = [0, 1, 0];
var setsomething = 2;

function setChild(ind) {
    var ev = "arr";
    for (var i = 0; i < ind.length; i++) {
        if (i + 1 < ind.length) {
            ev += '[' + ind[i] + ']["child"]';
        } else {
            ev += '[' + ind[i] + ']["text"]'
        }
    }
    ev += '=' + setsomething.toString() + ";";
    console.log(ev);
    console.log("original array");
    console.log(arr);
    eval(ev);
     console.log("Modified array");
    console.log(arr);
}
setChild(ind);
Zorak
  • 709
  • 7
  • 24