Search code examples
javascriptrecursiontreetreeview

How do I filter a tree by a non-existing property in parent


I have a structure like this:

const tree = [
  {
    "a": "1",
    "children": [
      {
        "a": "11",
        "children": [
            { "a": "111", "p": "me" }, 
            { "a": "112" }
        ]
      },
      { "a": "111", "p": "me" }
    ]
  },
  { "a": "2" },
  { "text": "3", "p": "me" }
]

And I'm trying to filter the tree by p: "me", however, I keep bumping into the parent and can't get past it. My desired output is something in these lines:

const res = filter(tree, "p", "me")
console.log(res)
/*
[
  {
    "a": "1",
    "children": [
      {
        "a": "11",
        "children": [
            { "a": "111", "p": "me" }, 
        ]
      },
      { "a": "111", "p": "me" }
    ]
  },
  { "text": "3", "p": "me" }
]
*/

I've tried other solutions and tweak them (like this one), but I'm struggling


Solution

  • Check my comments in code.

    The trick is to know when to go into recursion to go deeper in the tree and when to return the true/false for the JS filter() method.

    const tree = [
      {
        "a": "1",
        "children": [
          {
            "a": "11",
            "children": [
                { "a": "111", "p": "me" }, 
                { "a": "112" }
            ]
          },
          { "a": "111", "p": "me" }
        ]
      },
      { "a": "2" },
      { "text": "3", "p": "me" }
    ]
    
    const filter = (array, property, value) => {
      // Filter an array...
      return array.filter((object) => {
        // If an object of the array has a 'children'
        if(object.children){
          // It goes into recursion to set the filtered 'children'
          object.children = filter(object.children, property, value)
          // Then returns true if the children array is not empty
          return object.children.length
        }
        // If the object has a 'p' === 'me' (passed as arguments), it returns true (or false to discards the object)
        return object[property] === value
      })
    }
    
    console.log(filter(tree, "p", "me"))