vendredi 13 octobre 2017

How to enable a javascript loop to recursively iterate an unknown number of times?

I've run across a type of problem I'm not familiar with in javascript. I'm guessing there is likely a straightforward approach to solving this sort of problem, but I am unclear what it might be.

  • I have an array which contains a series of objects.
  • Each of those objects may (or may not) contain a deeper array which contains a series of objects.
  • Each of those objects may (or may not) contain a deeper array which contains a series of objects
  • (and so on...)

I need to process each object in each series of objects, so writing a function which runs a for loop which I can repeatedly invoke seems the obvious approach.

But... (here's the issue)... since the function may invoke itself a repeated number of times, how can I write a loop which keeps going deeper into the object, as deep as it needs to?

Here's an example...

With this object:

{
  "level1": [
    {
      "FirstItem": "one",
      "SecondItem": "two",
      "ThirdItem": [
        {
          "FirstItem": "three",
          "SecondItem": "four"
        }
      ]
    },
    {
      "FirstItem": "five",
      "SecondItem": "six",
      "ThirdItem": [
        {
          "FirstItem": "seven",
          "SecondItem": "eight"
        }
      ]
    }
  ]
}

I can log the values in the right order using this nested loop:

for (var i = 0; i < Object.keys(myObject.level1).length; i++) {

    for (var j = 0; j < (Object.values(myObject.level1[i]).length); j++) {

        if (typeof Object.values(myObject.level1[i])[j] === 'string') {
            console.log(Object.values(myObject.level1[i])[j]);
        }

        else {

            for (var k = 0; k < Object.values(myObject.level1[i])[j].length; k++) {

                for (var l = 0; l < (Object.values(Object.values(myObject.level1[i])[j][k]).length); l++) {

                    if (typeof Object.values(Object.values(myObject.level1[i])[j][k])[l] === 'string') {
                    console.log(Object.values(Object.values(myObject.level1[i])[j][k])[l]);
                    }
                }
            }
        }
    }
}

Proof:

var myObject = {};
myObject['level1'] = [];

myObject.level1[0] = {FirstItem: 'one', SecondItem: 'two'};
myObject.level1[0]['ThirdItem'] = [];

myObject.level1[1] = {FirstItem: 'five', SecondItem: 'six'};
myObject.level1[1]['ThirdItem'] = [];

myObject.level1[0].ThirdItem[0] = {FirstItem: 'three', SecondItem: 'four'};
myObject.level1[1].ThirdItem[0] = {FirstItem: 'seven', SecondItem: 'eight'};

for (var i = 0; i < Object.keys(myObject.level1).length; i++) {

    for (var j = 0; j < (Object.values(myObject.level1[i]).length); j++) {

        if (typeof Object.values(myObject.level1[i])[j] === 'string') {
            console.log(Object.values(myObject.level1[i])[j]);
        }
    
        else {
            
            for (var k = 0; k < Object.values(myObject.level1[i])[j].length; k++) {
                 
                for (var l = 0; l < (Object.values(Object.values(myObject.level1[i])[j][k]).length); l++) {

                    if (typeof Object.values(Object.values(myObject.level1[i])[j][k])[l] === 'string') {
                    console.log(Object.values(Object.values(myObject.level1[i])[j][k])[l]);
                    }
                }
            }
        }
    }
}

But... the loop is absolutely horrible. It's verbose and ugly. And, if it were required to go even deeper into the object, how on earth would it then come up with the iterators m, n, o and p?

I am guessing that another type of loop (like while or do... while) might be a better approach, but it's not clear to me how javascript can ascertain the depth of the object.

Ultimately, I am speculating that this is just an example of a pattern that I am unfamiliar with and I am using the wrong tools, awkwardly, to produce the right result.

Aucun commentaire:

Enregistrer un commentaire