Csaba
Csaba

Reputation: 2096

How to get the maximum depth of a multidimensional array in JS?

I have a multidimensional array and I would like to know the maximum depth of it.

I have found this soultion however it doesn't work with array of objects:

const getArrayDepth = (arr) => {
  return Array.isArray(arr) ? 1 + Math.max(...arr.map(getArrayDepth)) : 0;
}
const a = [1, [[2, 3, [[4], 5], 6, [7, 8]], 9, [10, [[[11]]]], 12, 13], 14];

const b = [{
  "name": "Car Parts",
  "children": [{
    "name": "Body Parts",
    "children": [{
      "name": "Bumpers & Components",
      "children": [{
        "name": "Bumper Grilles",
        "children": []
      }]
    }]
  }, {
    "name": "Engine Parts",
    "children": [{
      "name": "Alternators",
      "children": []
    }, {
      "name": "Injectors",
      "children": []
    }]
  }]
}, {
  "name": "Wheels",
  "children": [{
    "name": "Alloy Wheels",
    "children": []
  }]
}, {
  "name": "Lubricants & Coolants",
  "children": []
}];

console.log(`A: ${getArrayDepth(a)} ✓`);
console.log(`B: ${getArrayDepth(b)} X (should be 4) `);

How can I convert this code to work with my array?

Upvotes: 1

Views: 1933

Answers (2)

xdeepakv
xdeepakv

Reputation: 8135

The second array has object, so u have to modify the solution for object which is not array..

If you are using es6 or more, you can use the Object.values

const getArrayDepth = arr => {

  return Array.isArray(arr) ? 1 + Math.max(...arr.map(getArrayDepth)) : typeof(arr) === 'object' ? Math.max(...Object.values(arr).map(getArrayDepth)): 0;
};

Working solution:

const getArrayDepth = arr => {

  return Array.isArray(arr) ? 1 + Math.max(...arr.map(getArrayDepth)) : typeof(arr) === 'object' ? Math.max(...Object.values(arr).map(getArrayDepth)): 0;
};
const a = [1, [[2, 3, [[4], 5], 6, [7, 8]], 9, [10, [[[11]]]], 12, 13], 14];

const b = [
  {
    name: "Car Parts",
    children: [
      {
        name: "Body Parts",
        children: [
          {
            name: "Bumpers & Components",
            children: [
              {
                name: "Bumper Grilles",
                children: []
              }
            ]
          }
        ]
      },
      {
        name: "Engine Parts",
        children: [
          {
            name: "Alternators",
            children: []
          },
          {
            name: "Injectors",
            children: []
          }
        ]
      }
    ]
  },
  {
    name: "Wheels",
    children: [
      {
        name: "Alloy Wheels",
        children: []
      }
    ]
  },
  {
    name: "Lubricants & Coolants",
    children: []
  }
];

console.log(`A: ${getArrayDepth(a)} ✓`);
console.log(`B: ${getArrayDepth(b)} X (should be 4) `);

Upvotes: 3

Heretic Monkey
Heretic Monkey

Reputation: 12106

The argument arr is either an array, or not. When it's not, it's either an object with a children array (that has elements), or not. When that's not, return 0. Otherwise, recurse over children.

const getArrayDepth = (arr) => {
  return Array.isArray(arr) ? // if arr is an array, recurse over it
    1 + Math.max(...arr.map(getArrayDepth)) : 
    Array.isArray(arr.children) && arr.children.length ? // if arr is an object with a children property, recurse over the children
      1 + Math.max(...arr.children.map(getArrayDepth)) : 
      0; // otherwise, it's 0
}
const a = [1, [[2, 3, [[4], 5], 6, [7, 8]], 9, [10, [[[11]]]], 12, 13], 14];

const b = [{
  "name": "Car Parts",
  "children": [{
    "name": "Body Parts",
    "children": [{
      "name": "Bumpers & Components",
      "children": [{
        "name": "Bumper Grilles",
        "children": []
      }]
    }]
  }, {
    "name": "Engine Parts",
    "children": [{
      "name": "Alternators",
      "children": []
    }, {
      "name": "Injectors",
      "children": []
    }]
  }]
}, {
  "name": "Wheels",
  "children": [{
    "name": "Alloy Wheels",
    "children": []
  }]
}, {
  "name": "Lubricants & Coolants",
  "children": []
}];

console.log(`A: ${getArrayDepth(a)} ✓`);
console.log(`B: ${getArrayDepth(b)} X (should be 4) `);

Here it is again, using if statements rather than nested ternaries. I think it's a bit clearer this way, but it's really just an opinion.

const getArrayDepth = (arr) => {
  if (Array.isArray(arr)) {
    // if arr is an array, recurse over it
    return 1 + Math.max(...arr.map(getArrayDepth));
  }
  if (arr.children && arr.children.length) {
    // if arr is an object with a children property, recurse over the children
    return 1 + Math.max(...arr.children.map(getArrayDepth));
  }
  return 0;
}
const a = [1, [[2, 3, [[4], 5], 6, [7, 8]], 9, [10, [[[11]]]], 12, 13], 14];

const b = [{
  "name": "Car Parts",
  "children": [{
    "name": "Body Parts",
    "children": [{
      "name": "Bumpers & Components",
      "children": [{
        "name": "Bumper Grilles",
        "children": []
      }]
    }]
  }, {
    "name": "Engine Parts",
    "children": [{
      "name": "Alternators",
      "children": []
    }, {
      "name": "Injectors",
      "children": []
    }]
  }]
}, {
  "name": "Wheels",
  "children": [{
    "name": "Alloy Wheels",
    "children": []
  }]
}, {
  "name": "Lubricants & Coolants",
  "children": []
}];

console.log(`A: ${getArrayDepth(a)} ✓`);
console.log(`B: ${getArrayDepth(b)} X (should be 4) `);

Upvotes: 4

Related Questions