0

I want to find all occurances of keys and change its value. I want the id and name to be changed in the entire object to a new value.

const myObj = {
  id: 1,
  name: "a",
  children: [
    {
      id: 2,
      name: "b",
      children: [
        {
          id: 3,
          name: "c",   
        }
      ]
    },
    {
      id: 4,
      name: "d",
      children: [
        {
          id: 5,
          name: "e",
          children: [
            {
              id: 6,
              name: "f",
              children: [
                {
                  id: 7,
                  name: "g",  
                }
              ]
            }
          ]
        }
      ]
    },
  ]
}

Code which i tried, not sure how can i get two properties and change their values.

function findAllByKey(obj, id, name) {
  let constObj = Object.entries(obj);
  console.log(obj)
  Object.entries(constObj)
    .reduce(([key, value]) => (key === id)
      ? obj[key] = "123"
      : (typeof value === 'object'))
      
  return obj;
}

// USAGE, 
console.log(findAllByKey(myObj, 'id', 'name'))
Thalapathy
  • 127
  • 1
  • 1
  • 12

1 Answers1

1

You will need to utilize recursion for this.

Dave Newton gives a good argument in saying that the children properties are the ones containing most of the properties you want to change, so I would recommend you loop through each of the children properties and change their ID in that way. However, the answer I give you will work in more generic instances (for those who may need a different approach).

function findAllByKeyAndReplace(object,key,replace){
  const looper = function(obj){
    for (let k in obj){
      if(k === key){
        obj[k] = replace;
      }
      else if("object" === typeof obj[k]){
        looper(obj[k]);
      }
    }
  }
  looper(object);
}
const myObj = {
  id: 1,
  name: "a",
  children: [
    {
      id: 2,
      name: "b",
      children: [
        {
          id: 3,
          name: "c",   
        }
      ]
    },
    {
      id: 4,
      name: "d",
      children: [
        {
          id: 5,
          name: "e",
          children: [
            {
              id: 6,
              name: "f",
              children: [
                {
                  id: 7,
                  name: "g",  
                }
              ]
            }
          ]
        }
      ]
    },
  ]
}
findAllByKeyAndReplace(myObj,"id","123");
findAllByKeyAndReplace(myObj,"name","pickles");
console.log(myObj);

Note that I am pretty old school about this so please tell me if there is any way to improve on this, as it does take up a bit of power.

Oh wait, I see you want to return a list of the objects and not bulk-replace them with one value. Ok, that is quite easily done, too.

Instead of changing them just add them to an array which will be returned on the looper being finished:

function findAllByKey(object, key) {
  const collection = [];
  const looper = function(obj) {
    for (let k in obj) {
      if (k === key) {
        collection.push(obj[k]);
      } else if ("object" === typeof obj[k]) {
        looper(obj[k]);
      }
    }
  }
  looper(object);
  return collection;
}
const myObj = {
  id: 1,
  name: "a",
  children: [{
      id: 2,
      name: "b",
      children: [{
        id: 3,
        name: "c",
      }]
    },
    {
      id: 4,
      name: "d",
      children: [{
        id: 5,
        name: "e",
        children: [{
          id: 6,
          name: "f",
          children: [{
            id: 7,
            name: "g",
          }]
        }]
      }]
    },
  ]
}
console.log(findAllByKey(myObj, "id"));
console.log(findAllByKey(myObj, "name"));
Reality
  • 637
  • 1
  • 6
  • 25
  • I was trying with reduce and recurssion, but seems some where its messing up. https://jsfiddle.net/smugjor8/ – Thalapathy Mar 07 '21 at 21:01
  • I'm not that advanced in Object.entries and such, but why use `reduce`? Can't you use `.forEach`? – Reality Mar 07 '21 at 21:09
  • @Reality Anything that can be solved with recursion can be solved with iteration. So, the OP doesn't _need_ to use recursion. There are situations where iteration would be preferred to minimize the depth of the call stack. Ref: https://stackoverflow.com/questions/931762/can-every-recursion-be-converted-into-iteration/933979#933979 – Matt Morgan Mar 07 '21 at 21:09
  • @MattMorgan Huh, I'll have to look into that sometime. I'm not good when it comes to advanced logic though, I'll have to improve on that a bit. For those of us deprived of advanced (or higher) knowledge of logic and mathematics though, recursion is good for the moment. – Reality Mar 07 '21 at 21:13