1

I have an array which looks like this:

var arrayElements=
[
        ["1","description 1",
            [
                ["1.1","description 1.1"],
                ["1.2","description 1.2"],
                ["1.2","description 1.3"]
            ]
        ]
        ,
        ["2","description 2"],
        ["3","description 3",
            [
                ["3.1","description 3.1"],
                ["3.2","description 3.2",
                    [
                        ["3.2.1","description 3.2.1"],
                        ["3.2.2","description 3.2.2"],
                        ["3.2.2","description 3.2.3"]
                    ]
                ],
                ["3.3","description 3.3"]
            ]
        ],
        ["4","description 4"]
];

I want to loop trough the following array, be able to access all values as well as print depth of each element. Expected outcome in console would be something like this:

description 1, depth 1
description 1.1, depth 2
description 1.2, depth 2
description 1.3, depth 2
description 2, depth 1
description 3, depth 1
description 3.1, depth 2
description 3.2, depth 2
description 3.2.1, depth 3
description 3.2.2, depth 3
description 3.2.3, depth 3
description 3.3, depth 2
description 4, depth 1

Here's what I have tried:

var depth = 0;

function listNodes(array){

    for(i = 0; i < array.length;i++){
        if( /* itearating over root array */ ){
            depth = 1;
        }

        if(array[i][2] instanceof Array){
            depth++;
            console.log(array[i][1] + " depth: "+depth);
            listNodes(array[i][2]);
        }else{
            console.log(array[i][1] + " depth: "+depth);
        }
    }
}

listNodes(arrayElements);

I'm unable to loop through this array, it gets stuck even though it should continue. Another problem is the fact that my variable storing depth is not working as I'm unable to determine when the loop iterates over the root array so that I can reset the depth counter. Any ideas?

1
  • depth must be function parameter, not shared variable.
    – hindmost
    Commented May 15, 2017 at 8:21

3 Answers 3

1

var arrayElements=
[
        ["1","description 1",
            [
                ["1.1","description 1.1"],
                ["1.2","description 1.2"],
                ["1.2","description 1.3"]
            ]
        ]
        ,
        ["2","description 2"],
        ["3","description 3",
            [
                ["3.1","description 3.1"],
                ["3.2","description 3.2",
                    [
                        ["3.2.1","description 3.2.1"],
                        ["3.2.2","description 3.2.2"],
                        ["3.2.2","description 3.2.3"]
                    ]
                ],
                ["3.3","description 3.3"]
            ]
        ],
        ["4","description 4"]
];

function listNodes(array, depth) {
    depth = typeof depth === 'undefined' ? 1 : depth;

	var len = array.length;

    for(var i = 0; i < array.length;i++) {
        console.log(array[i][1] + " depth: "+ depth);
        
        if(array[i][2] instanceof Array) {
           listNodes(array[i][2], depth + 1);
        }
    }
}

listNodes(arrayElements);

This gives me the exact output from your example. Note that I'm passing the depth as a parameter to the function.

1
  • Thank you. Adding parameter is solution I was looking for, I was not able to come up with an idea of resetting depth counter other way than by storing it's value in variable. Commented May 15, 2017 at 8:38
1

It would be prettier and more flexible if you could use objects instead of remembering indexes:

var arrayElements = [{
    id: "1",
    description: "description 1",
    children: [{
      id: "1.1",
      description: "description 1.1",
      children: []
    }]
  },
  {
    id: "2",
    description: "description 2",
    children: [{
      id: "2.1",
      description: "description 2.1",
      children: [{
          id: "2.1.1",
          description: "description 2.1.1",
          children: []
        },
        {
          id: "2.1.2",
          description: "description 2.1.2",
          children: []
        }
      ]
    }]
  }
];

function deepSearch(arr, depth, cb) {
  if (depth === void 0) {
    depth = 0;
  }
  if (cb === void 0) {
    cb = function(val) {
      console.log(val);
    };
  }
  for (var i = 0; i < arr.length; i++) {
    var val = arr[i];
    cb(val.id + " - " + val.description + " at depth " + depth);
    if (val.children.length > 0) {
      deepSearch(val.children, depth + 1, cb);
    }
  }
}
deepSearch(arrayElements);

0

You can do something like this

function listNodes(array, depth) {
    depth++;
    for (let i = 0; i < array.length; i++) {
        console.log(array[i][1] + ' - ' + depth);
        if (typeof array[i][2] === 'object') {
            listNodes(array[i][2], depth);
        }
    }
}

listNodes(arrayElements, 0);

Considering your example o/p of this will be:

description 1 - 1
description 1.1 - 2
description 1.2 - 2
description 1.3 - 2
description 2 - 1
description 3 - 1
description 3.1 - 2
description 3.2 - 2
description 3.2.1 - 3
description 3.2.2 - 3
description 3.2.3 - 3
description 3.3 - 2
description 4 - 1

Not the answer you're looking for? Browse other questions tagged or ask your own question.