Homelab, Linux, JS & ABAP (~˘▾˘)~
 

[JavaScript] Find specific object from an array of nested objects

I was again working on a task for my hierarchical tree structure (see previous post here). This time I needed to find a specific object with a specific property value.

So here again my nested array:

const aTreeData = [{
    "NodeId": 1,
    "HierarchyLevel": 1,
    "type": "folder",
    "nodes": [{
        "NodeId": 2,
        "HierarchyLevel": 2,
        "type": "folder",
        "nodes": [{
          "NodeId": 3,
          "HierarchyLevel": 3,
          "type": "category"
        }]
      },
      {
        "NodeId": 4,
        "HierarchyLevel": 2,
        "type": "category",
        "nodes": [{
          "NodeId": 5,
          "HierarchyLevel": 3,
          "type": "file"
        }]
      }
    ]
  },
  {
    "NodeId": 6,
    "HierarchyLevel": 1,
    "type": "folder",
    "nodes": [{
      "NodeId": 7,
      "HierarchyLevel": 2,
      "type": "category"
    }]
  }
]

I needed a function that was able to find any object by providing only the NodeId value. Fortunately I stumbled accross some excellent code snippet by Scott Sauyet which is exactly doing what I needed:

https://stackoverflow.com/questions/68559392/find-object-from-an-array-of-nested-objects-by-key-in-javascript

I just had to change the properties to match my objects and it was working!

const findNodeInTreeData = (aTreeData, nodeId) => {
  const deepFind = pred => ([x, ...xs] = []) =>
    x && (pred(x) ? x : deepFind(pred)(x.nodes) || deepFind(pred)(xs))

  const findByNodeId = id => obj =>
    deepFind(o => o.NodeId == id)([obj])

  return findByNodeId(nodeId)(aTreeData[0])
}

console.log(findNodeInTreeData(aTreeData, 5))

[JavaScript] Itereate through array of nested objects and delete specific objects

[
    {
        "NodeId": 1,
        "HierarchyLevel": 1,
        "type": "folder",
        "nodes": [
            {
                "NodeId": 2,
                "HierarchyLevel": 2,
                "type": "folder",
                "nodes": [
                    {
                        "NodeId": 3,
                        "HierarchyLevel": 3,
                        "type": "category"
                    }
                ]
            },
            {
                "NodeId": 4,
                "HierarchyLevel": 2,
                "type": "category",
                "nodes": [
                    {
                        "NodeId": 5,
                        "HierarchyLevel": 3,
                        "type": "file"
                    }
                ]
            }
        ]
    },
    {
        "NodeId": 6,
        "HierarchyLevel": 1,
        "type": "folder",
        "nodes": [
            {
                "NodeId": 7,
                "HierarchyLevel": 2,
                "type": "category"
            }
        ]
    }
]

My task was to get rid of every Node which has no subnodes of type file at the last level of the hierachy. So for this example the result I needed was an array containing only the nodes 1,2,4,5.
Of course in reality the nested structure was way more complex. My approach was a recursive function which checks every element’s type and nodes length property and calls itself if there are any subnodes. Also it is recommended to loop backwards through the array while deleting from it.

            
            const removeEmptyNodes = nodes => {
                for (let i = nodes.length - 1; i > -1; i--) {
                    const n = nodes[i]
                    //call function recursive to go deeper through the nested structure
                    if (n.nodes) removeEmptyNodes(n.nodes)                        
                    //remove element if it's not a file and has no subnodes
                    if (n.type !== 'file' && (!n.nodes || n.nodes.length === 0)) nodes.splice(i, 1)
                }
            }

            // nodes contains the array data from above
            removeEmptyNodes(nodes)