-4

I have the following object which have nested object and arrays:

{
  "children":[
    {
      "id":"9737ea0a-fa6f-42e1-bf16-a10af80e4d50",
      "isCriteria":false,
      "name":"Domain 1",
      "children":[
        {
          "id":"e06d1940-b480-48e2-8e1a-2fe2a3910dfd",
          "children":[
            {
              "id":"30995e1e-7195-4d01-85bf-c621398796cc",
              "children":[
                {
                  "id":"2969e48d-615e-4774-b92e-cbce768503ff",
                  "children":[

                  ],
                  "isCriteria":true,
                  "name":"Criteria 1",
                  "questionType":"Yes/NO",
                  "importance":3
                }
              ],
              "isCriteria":false,
              "name":"sub domain 1 - 2"
            }
          ],
          "isCriteria":false,
          "name":"Sub domain 1"
        },
        {
          "id":"c5b36f02-e765-4d93-970c-6faca94c28c1",
          "children":[
            {
              "id":"6807ea4f-fb14-4d68-98f4-b3bf4c601e5c",
              "children":[

              ],
              "isCriteria":true,
              "name":"Criteria 2",
              "questionType":"5",
              "importance":"1"
            }
          ],
          "isCriteria":false,
          "name":"sub domain 2"
        }
      ]
    }
  ]
}

I want to loop through it children until i got to the tail. and edit that tail with other data, for .. in wont work since i have arrays

3
  • see: stackoverflow.com/questions/10459917/… Commented Aug 22, 2019 at 17:01
  • Why won't ? When used with arrays, it will give you indexes Commented Aug 22, 2019 at 17:02
  • You can check node.isCriteria for true if you want to stop recursing too. Commented Aug 22, 2019 at 17:39

2 Answers 2

1

You can easily do this recursively.

function recurse(node, level=0) {
  if (node == null) return; // Check for null, exit
  console.log(node.id == null ? 'root' : node.id); // Print the ID
  if (node.children) node.children.forEach(child => recurse(child, level + 1)); // Hand off to children
}

Example Output from code below.

root
↓ ID: 9737ea0a-fa6f-42e1-bf16-a10af80e4d50
    ↳ Name: Domain 1
  ↓ ID: e06d1940-b480-48e2-8e1a-2fe2a3910dfd
      ↳ Name: Sub domain 1
    ↓ ID: 30995e1e-7195-4d01-85bf-c621398796cc
        ↳ Name: sub domain 1 - 2
      ↳ ID: 2969e48d-615e-4774-b92e-cbce768503ff
          ↳ Name: Criteria 1
          ↳ Type: Yes/NO
          ↳ Importance: 3
  ↓ ID: c5b36f02-e765-4d93-970c-6faca94c28c1
      ↳ Name: sub domain 2
    ↳ ID: 6807ea4f-fb14-4d68-98f4-b3bf4c601e5c
        ↳ Name: Criteria 2
        ↳ Type: 5
        ↳ Importance: 1

const data = loadData();

recurse(data);

function recurse(node, level=0) {
  if (node == null) return;
  let symbol = node.isCriteria ? '↳' : '↓';
  let paddingOuter = ''.padStart((level - 1) * 2, ' ');
  let paddingInner = ''.padStart((level + 1) * 2, ' ');
  console.log(node.id == null ? 'root' : paddingOuter + symbol + ' ID: ' +  node.id);
  if (node.name) console.log(paddingInner + '↳ Name: ' + node.name);
  if (node.isCriteria) {
    console.log(paddingInner + '↳ Type: ' + node.questionType);
    console.log(paddingInner + '↳ Importance: ' + node.importance);
  }
  if (node.children) node.children.forEach(child => recurse(child, level + 1));
}

function loadData() {
  return {
    "children": [{
      "id": "9737ea0a-fa6f-42e1-bf16-a10af80e4d50",
      "isCriteria": false,
      "name": "Domain 1",
      "children": [{
          "id": "e06d1940-b480-48e2-8e1a-2fe2a3910dfd",
          "children": [{
            "id": "30995e1e-7195-4d01-85bf-c621398796cc",
            "children": [{
              "id": "2969e48d-615e-4774-b92e-cbce768503ff",
              "children": [

              ],
              "isCriteria": true,
              "name": "Criteria 1",
              "questionType": "Yes/NO",
              "importance": 3
            }],
            "isCriteria": false,
            "name": "sub domain 1 - 2"
          }],
          "isCriteria": false,
          "name": "Sub domain 1"
        },
        {
          "id": "c5b36f02-e765-4d93-970c-6faca94c28c1",
          "children": [{
            "id": "6807ea4f-fb14-4d68-98f4-b3bf4c601e5c",
            "children": [

            ],
            "isCriteria": true,
            "name": "Criteria 2",
            "questionType": "5",
            "importance": "1"
          }],
          "isCriteria": false,
          "name": "sub domain 2"
        }
      ]
    }]
  };
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

Editing data

If you need to edit a particular node, you can locate it by its ID and assign a "new" object to it. It will override existing and add new properties.

function editNode(node, id, payload={}, found=false) {
  if (node == null || id == null || found === true) return;
  if (node.id === id) {
    Object.assign(node, payload);
    found = true;
  }
  if (found === false && node.children) {
    node.children.forEach(child => editNode(child, id, payload, found));
  }
}
 ↳ ID: 6807ea4f-fb14-4d68-98f4-b3bf4c601e5c
     ↳ Name: Criteria 2
     ↳ Question Type: 99 <-- MODIFIED BELOW
     ↳ Importance: 1

const data = loadData();

editNode(data, '6807ea4f-fb14-4d68-98f4-b3bf4c601e5c', { questionType : 99 })
recurse(data);

function recurse(node, level=0) {
  if (node == null) return;
  let symbol = node.isCriteria ? '↳' : '↓';
  let paddingOuter = ''.padStart((level - 1) * 2, ' ');
  let paddingInner = ''.padStart((level + 1) * 2, ' ');
  console.log(node.id == null ? 'root' : paddingOuter + symbol + ' ID: ' +  node.id);
  if (node.name) console.log(paddingInner + '↳ Name: ' + node.name);
  if (node.isCriteria) {
    console.log(paddingInner + '↳ Question Type: ' + node.questionType);
    console.log(paddingInner + '↳ Importance: ' + node.importance);
  }
  if (node.children) node.children.forEach(child => recurse(child, level + 1));
}

function editNode(node, id, payload={}, found=false) {
  if (node == null || id == null || found === true) return;
  if (node.id === id) {
    Object.assign(node, payload);
    found = true;
  }
  if (found === false && node.children) {
    node.children.forEach(child => editNode(child, id, payload, found));
  }
}

function loadData() {
  return {
    "children": [{
      "id": "9737ea0a-fa6f-42e1-bf16-a10af80e4d50",
      "isCriteria": false,
      "name": "Domain 1",
      "children": [{
          "id": "e06d1940-b480-48e2-8e1a-2fe2a3910dfd",
          "children": [{
            "id": "30995e1e-7195-4d01-85bf-c621398796cc",
            "children": [{
              "id": "2969e48d-615e-4774-b92e-cbce768503ff",
              "children": [

              ],
              "isCriteria": true,
              "name": "Criteria 1",
              "questionType": "Yes/NO",
              "importance": 3
            }],
            "isCriteria": false,
            "name": "sub domain 1 - 2"
          }],
          "isCriteria": false,
          "name": "Sub domain 1"
        },
        {
          "id": "c5b36f02-e765-4d93-970c-6faca94c28c1",
          "children": [{
            "id": "6807ea4f-fb14-4d68-98f4-b3bf4c601e5c",
            "children": [

            ],
            "isCriteria": true,
            "name": "Criteria 2",
            "questionType": "5",
            "importance": "1"
          }],
          "isCriteria": false,
          "name": "sub domain 2"
        }
      ]
    }]
  };
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

Sign up to request clarification or add additional context in comments.

Comments

0

You can use Object.keys on either an array or an object and then iterate through those.. this is just a quick and dirty example of that.

var data = {
  "children": [{
    "id": "9737ea0a-fa6f-42e1-bf16-a10af80e4d50",
    "isCriteria": false,
    "name": "Domain 1",
    "children": [{
        "id": "e06d1940-b480-48e2-8e1a-2fe2a3910dfd",
        "children": [{
          "id": "30995e1e-7195-4d01-85bf-c621398796cc",
          "children": [{
            "id": "2969e48d-615e-4774-b92e-cbce768503ff",
            "children": [],
            "isCriteria": true,
            "name": "Criteria 1",
            "questionType": "Yes/NO",
            "importance": 3
          }],
          "isCriteria": false,
          "name": "sub domain 1 - 2"
        }],
        "isCriteria": false,
        "name": "Sub domain 1"
      },
      {
        "id": "c5b36f02-e765-4d93-970c-6faca94c28c1",
        "children": [{
          "id": "6807ea4f-fb14-4d68-98f4-b3bf4c601e5c",
          "children": [],
          "isCriteria": true,
          "name": "Criteria 2",
          "questionType": "5",
          "importance": "1"
        }],
        "isCriteria": false,
        "name": "sub domain 2"
      }
    ]
  }]
};

function loopStuff(obj, cb){
  Object.keys(obj).forEach((key, idx)=>{
     var val = obj[key];
     if("object" === typeof val) loopStuff(val, cb);
     else cb(val);
  });
}

loopStuff(data, itm=>{
  console.log(itm);
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.