1

I have a problem which requires a function that can recursively traverse a nested array of objects and filter elements out based on whether or not they are present in a list of views.

For example, given a list:

[{
    "label": "Heading",
    "items": [{
      "label": "Subheading",
      "items": [{
          "id": "item1_priv",
          "label": "item1"
        },
        {
          "id": "item_priv2",
          "label": "item2"
        },
        {
          "label": "Subheading",
          "items": [{
            "id": "item_priv3",
            "label": "item3"
          }]
        }
      ]
    }]
  },
  {
    "label": "Heading2",
    "items": [{
      "label": "Subheading",
      "items": [{
          "id": "item_priv4",
          "label": "item4"
        },
        {
          "id": "item_priv5",
          "label": "item5"
        }
      ]
    }]
  }
]

and a list of views:

canView = ['item1','item2','item4','item5']

The function needs to filter out item3 in the list as it is not present in canView.

I have already made a function that does this:

public filterView(list: any[]): any {

  for (const item of list) {
    if (item.items) {
      item.items = this.filterView(item.items);
    } else {
      list = ((list.filter((i: any) => this.hasView(i.id))));
    }
  }

  return list;
}

However, my question is: Is it possible to rewrite this function as a lambda using list.filter()? I'm new to Angular to and Typescript so I'm having a tough time wrapping my head around using filter (or nested filters) in order to traverse the list based on whether not it possesses items.

my assumption would be a function along the lines of

list.filter(item => return(item.items && this.hasView(item.items.id)))

but this doesn't seem to work on a list with dynamic depth. Any advice would be appreciated as other solutions to similar problems I've seen have only had lists with fixed depths.

2
  • What is hasView expected to return? Commented Oct 14, 2018 at 7:40
  • hasView returns a boolean based on whether or not the id of the item is present in the canView list. Commented Oct 14, 2018 at 7:50

1 Answer 1

1

The only change I would suggest is to do the list filtering once rather than inside the loop:

public filterView(list: any[]): any {

  for (const item of list) {
    if (item.items) {
      item.items = this.filterView(item.items);
    }
  }

  return list.filter((i: any) => this.hasView(i.id));
}

Beyond that, given that filterView is doing two different things (filtering the top-level list and mutating the child lists of the descendants), it seems to me that any more concise way of writing it is going to be harder to understand.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.