0

I want to set a boolean value in a nested object structure, based on a list of indexes

The data I want to update looks like this:

let categories = [{
    "name": "Cat 1",
    "subs": [{
        "name": "Sub Cat 1.1",
        "subs": [],
        "checked": false
      },
      {
        "name": "Sub Cat 1.2",
        "subs": [],
        "checked": false
      }
    ],
    "checked": false
  },
  {
    "name": "Cat 2",
    "subs": [],
    "checked": false
  }
];

The indexes are stored in an array:

let categoryIndexs = [0,1]

So based on categoryIndexs I want to change the checked property of the object with name "Sub Cat 1.2" to true.

It is like transforming the array [0,1] to find categories[0].subs[1] and update its checked property.

So far I managed to get the value and edit it separately, but how to change the categories variable directly?

  let categoryIndexs = [0,1]

  let tmp_array = categories;

  for(var i = 0; i < categoryIndexs.length;i++){
      if(i == 0){
        tmp_array = tmp_array[categoryIndexs[i]]
      } else {
        tmp_array = tmp_array.subs[categoryIndexs[i]]
      }
  }

  tmp_array.checked = true
  console.log(tmp_array)

The solution needs to be dynamic, so that if "Sub Cat 1.2" would have a nested entry in its own subs array, I can access it using categoryIndexs like [0,1,0]

trincot
  • 317,000
  • 35
  • 244
  • 286
good112233
  • 144
  • 1
  • 10
  • 5
    Please visit the [help], take the [tour] to see what and [ask]. Do some research, search for related topics on SO; if you get stuck, post a [mcve] of your attempt, noting input and expected output using the `[<>]` snippet editor. – mplungjan May 27 '20 at 12:19
  • please add your code snippet you tried.. – Muhammad Iqbal May 27 '20 at 12:20
  • Question is not clear. – Soham May 27 '20 at 12:23
  • sorry for the mistake and thanks for the suggestion I've updated my question now I hope it meets the standards – good112233 May 27 '20 at 12:42
  • Does this answer your question? [How to insert an item into an array at a specific index (JavaScript)?](https://stackoverflow.com/questions/586182/how-to-insert-an-item-into-an-array-at-a-specific-index-javascript) – Fanchi May 27 '20 at 13:34

3 Answers3

2

You can iterate the given indexes in a loop and at the same time go deeper in your data structure, like in this function:

function setChecked(categories, categoryIndexes) {
    let obj = null;
    for (let index of categoryIndexes) {
        obj = categories[index];
        categories = obj.subs;
    }
    obj.checked = true;
}

let categories = [{"name": "Cat 1","subs": [{"name": "Sub Cat 1.1","subs": [],"checked": false},{"name": "Sub Cat 1.2","subs": [],"checked": false}],"checked": false},{"name": "Cat 2","subs": [],"checked": false}];
setChecked(categories, [0,1]);
console.log(categories);
trincot
  • 317,000
  • 35
  • 244
  • 286
2

You could use reduce to get the last subs up until the last subs and update the checked property

let categories = [{"name": "Cat 1","subs": [{"name": "Sub Cat 1.1","subs": [],"checked": false},{"name": "Sub Cat 1.2","subs": [],"checked": false}],"checked": false},{"name": "Cat 2","subs": [],"checked": false}];
let categoryIndexs = [0, 1];

function update(categories, indices) {
  const last = indices.pop(); // remove the last
  const redued = indices.reduce((acc, i) => acc[i].subs, categories);
  redued[last].checked = true;
  return categories
}

console.log(update(categories, categoryIndexs))
adiga
  • 34,372
  • 9
  • 61
  • 83
2

You could reduce the array by looking to the index of the iteration and take either subs or the item.

const 
    getValue = (subs, indices) => indices.reduce(
        ({ subs }, i) => subs[i],
        { subs }
    );

let categories = [{ name: "Cat 1", subs: [{ name: "Sub Cat 1.1", subs: [], checked: false }, { name: "Sub Cat 1.2", subs: [], checked: false }], checked: false }, { name: "Cat 2", subs: [], checked: false }],
    indices = [0, 1];

console.log(getValue(categories, indices, 'subs'));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392