Given a flat array of objects, I group the children items by pid (parent id) to the id's of the parents. My function does exactly that, but only two levels deep. How could I turn this function into a function that handles nesting of any depth?
This is the data:
const list = 
 [   
     { "pid": 0, "id": "solo"},
     { "pid": 0, "id": "member"},
     { "pid": 0, "id": "solo2"},
     { "pid": "member", "id": "10_admin_members"},
     { "pid": "member", "id": "10_invitations"},
     { "pid": "member", "id": "sub_member"},
     { "pid": "sub_member", "id": "other"},
     { "pid": "sub_member", "id": "other2"},
     { "pid": 0, "id": "admin"},
     { "pid": "admin", "id": "admin_general"},
     { "pid": "admin", "id": "admin_modules"},
     { "pid": "admin", "id": "admin_roles"},
     { "pid": "admin", "id": "admin_navigation"},
 ]
And the function:
const groupChildrenToParentsByKeys = (firstLevelItems, groupedItems, childArrayKey = 'items') 
 => {
  let cleanArray = []
  for (const a in firstLevelItems) {
      let childrenCount = 0
      for (const b in groupedItems) {
          if(firstLevelItems[a].id == b) {
              let descendantsArray = []
              let childrenArray = groupedItems[b]
                for (const c in childrenArray) {
                  let grandChildrenCount = 0
                  for (const h in groupedItems) {
                    if(childrenArray[c].id == h) {
                      let grandChildrenArray = groupedItems[h]
                      descendantsArray.push({...childrenArray[c], [childArrayKey]: grandChildrenArray})
                      grandChildrenCount ++
                    } 
                  }
                  if(!grandChildrenCount) {
                    descendantsArray.push(childrenArray[c])
                  }
                }
              cleanArray.push({...firstLevelItems[a], [childArrayKey]: descendantsArray})
              childrenCount ++
          }
      } 
      if(!childrenCount) {
        cleanArray.push(firstLevelItems[a])
      }
  }
  return cleanArray
}
const list = 
 [   
     { "pid": 0, "id": "solo"},
     { "pid": 0, "id": "member"},
     { "pid": 0, "id": "solo2"},
     { "pid": "member", "id": "10_admin_members"},
     { "pid": "member", "id": "10_invitations"},
     { "pid": "member", "id": "sub_member"},
     { "pid": "sub_member", "id": "other"},
     { "pid": "sub_member", "id": "other2"},
     { "pid": 0, "id": "admin"},
     { "pid": "admin", "id": "admin_general"},
     { "pid": "admin", "id": "admin_modules"},
     { "pid": "admin", "id": "admin_roles"},
     { "pid": "admin", "id": "admin_navigation"},
 ]
// Matches two objects by keys and inserts the children inside of parents as array
const groupChildrenToParentsByKeys = (firstLevelItems, groupedItems, childArrayKey = 'items') => {
    let cleanArray = []
    for (const a in firstLevelItems) {
        let childrenCount = 0
        for (const b in groupedItems) {
            if(firstLevelItems[a].id == b) {
                let descendantsArray = []
                let childrenArray = groupedItems[b]
                
                  for (const c in childrenArray) {
                    let grandChildrenCount = 0
                    for (const h in groupedItems) {
                      if(childrenArray[c].id == h) {
                        let grandChildrenArray = groupedItems[h]
                        descendantsArray.push({...childrenArray[c], [childArrayKey]: grandChildrenArray})
                        grandChildrenCount ++
                      } 
                    }
                    if(!grandChildrenCount) {
                      descendantsArray.push(childrenArray[c])
                    }
                  }
                cleanArray.push({...firstLevelItems[a], [childArrayKey]: descendantsArray})
                childrenCount ++
            }
        } 
        if(!childrenCount) {
          cleanArray.push(firstLevelItems[a])
        }
    }
    return cleanArray
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
let groupedObject = _.groupBy(list, 'pid') 
let firstLevel = {...groupedObject}[0]
let childrenParentArray = groupChildrenToParentsByKeys(firstLevel, groupedObject)
console.log(JSON.stringify(childrenParentArray, null, 2))
console.log(_.size(childrenParentArray))
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>