Recursively apply a custom condition to filter a tree

Within this tree structure, I need to extract items with a release version of 0.0.1 to use in building my navigation based on that specific release number.

{
  title: '',
  items: [
    {
      title: '',
      path: '',
      release: '0.0.1'
    },
    {
      title: '',
      path: '',
      release: '0.0.2'
    }
  ]
},
{
  title: '',
  items: [
    {
      title: '',
      items: [
        {
          title: '',
          path: '',
          release: '0.0.2'
        },
        {
          title: '',
          path: '',
          items: [
            {
              title: '',
              path: '',
              release: '0.0.1'
            },
            {
              title: '',
              path: '',
              release: '0.0.2'
            }
          ]
        }
      ]
    }
  ]
}

It's crucial to maintain the same tree structure for consistency when constructing the navigation menu.

{
  title: '',
  items: [
    {
      title: '',
      path: '',
      release: '0.0.1'
    },
  ]
},
{
  title: '',
  items: [
    {
      title: '',
      items: [
        {
          title: '',
          path: '',
          items: [
            {
              title: '',
              path: '',
              release: '0.0.1'
            },
          ]
        }
      ]
    }
  ]
}

I have succeeded in filtering two levels of nested trees as shown above, but encountered challenges when dealing with deeper levels of nesting within items.

const menuToggle = (condition) => (menus) => menus
  .map(menu => ({
    ...menu,
    items: menu.items.filter(item => condition(item))
  }))
  .filter(menu => !isEmpty(menu.items));

Answer №1

To construct your new array recursively, you can utilize the .reduce() method along with a recursive function called menuToggle. By checking for an items property in the current object, you can call menuToggle recursively to handle filtering and processing of child items arrays. The filtered items can then be spread onto the current object and added to the resulting array (acc). If there is no items property, the object can be checked against a condition and added to the accumulated array accordingly.

Here is an example:

const arr = [{ title: '', items: [{ title: '', path: '', release: '0.0.1' }, { title: '', path: '', release: '0.0.2' } ] }, { title: '', items: [{ title: '', items: [{ title: '', path: '', release: '0.0.2' }, { title: '', path: '', items: [{ title: '', path: '', release: '0.0.1' }, { title: '', path: '', release: '0.0.2' } ] } ] }] } ];

const menuToggle = (condition) => (menus) => {
  return menus.reduce((acc, obj) => {
    if(obj.items)
      return [...acc, {...obj, items: menuToggle(condition)(obj.items)}];
    else if(condition(obj))
      return [...acc, obj];
    return acc;
  }, []);
}

const res = menuToggle(({release}) => release === "0.0.1")(arr);
console.log(res);

If you wish to exclude objects generating empty items arrays, another check can be added:

const arr = [{ title: '', items: [{ title: '', path: '', release: '0.0.1' }, { title: '', path: '', release: '0.0.2' } ] }, { title: '', items: [{ title: '', items: [{ title: '', path: '', release: '0.0.2' }, { title: '', path: '', items: [{ title: '', path: '', release: '0.0.1' }, { title: '', path: '', release: '0.0.2' } ] } ] }] } ];

const menuToggle = (condition) => (menus) => {
  return menus.reduce((acc, obj) => {
    if(obj.items) {
      const items = menuToggle(condition)(obj.items);
      return items.length ? [...acc, {...obj, items }] : acc;
    } else if(condition(obj)) {
      return [...acc, obj];
    }
    return acc;
  }, []);
}

const res = menuToggle(({release}) => release === "0.0.1")(arr);
console.log(res);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Saving Files in Your React Web Application: Tips and Tricks

Currently, I am working on a React web application that requires the temporary storage of Torrent pieces for streaming purposes using a web player. Any recommendations on how to properly store this data temporarily in order to facilitate the streaming pro ...

Setting up webpack encore for async and await in a Symfony 4 and VueJs project

After setting up a VueJs project within Symfony 4, I encountered an unexpected error involving await and async (Uncaught ReferenceError: regeneratorRuntime is not defined) I've come across plenty of resources for webpack, but nothing specifically for ...

Validating numbers in React JS input fields component

I need assistance with implementing number validation for 3 Textfields in my application. Currently, the code displays an error message if a Textfield is empty, but I am stuck on validating whether the input is text or numbers. import React from 'rea ...

Rendering sibling components on Multiple Select Material UI in React

Here is my current challenge: I am trying to implement a multiple select feature with checkboxes in React using Material UI. The desired outcome should resemble the image linked below: https://i.stack.imgur.com/TJl8L.png I have structured my data in an a ...

Removing classes from multiple elements on hover and click in Vue 2

Can Vue be used to remove a class from an element? I am looking to remove the class when hovering over the element, and then add it back once the mouse is no longer on the text. Additionally, I want the class to be removed when the element is clicked. He ...

Is there a way to first run my validate function and then proceed with sending my AJAX request upon clicking a button?

Hey there! I've got a dynamic table generated from a database. You can check out the table. I have all the necessary code in place, but what I really need is to ensure proper timing of execution for specific actions: 1) Verify if all mandatory fields ...

Removing invalid characters in a *ngFor loop eliminates any elements that do not meet the criteria

I am facing an issue with my *ngFor loop that is supposed to display a list of titles. fetchData = [{"title":"woman%20.gif"},{"title":"aman",},{"title":"jessica",},{"title":"rosh&quo ...

Encountering a Module not found error with a ValidationError when trying to import an SVG file within a React

I've set up a manual Webpack 5 configuration for my React project with TypeScript. I am facing an issue while trying to import an SVG icon and using Material UI in the project. The error message I'm encountering is: Module not found: ValidationEr ...

Handling multiple patch requests using React and Redux when onBlur event occurs

Currently, I am using Redux-form for editing guest information. Whenever a field is left, the content of that field gets patched to the guest through a simple patch request and the store is updated accordingly. However, an issue arises when I use Google fo ...

Implementing Pagination in Vue: How to Make it Work with Response Data

I am looking to integrate pagination from the response data into my existing code, while also incorporating filters. JavaScript var entriesList = new Vue({ el: "#post-list-template", data: { posts: [], categories: [], cu ...

Anticipating the completion of a process.nextTick cycle

Problem Statement I am currently working on a Node.js application that involves complex calculations and utilizes recursive algorithms. The code snippet below gives a brief overview of how the calculations are performed: // routes.js - express.js routes ...

A secure method for dynamically adding a JavaScript file

In my lang folder, I store language variables for a website. To dynamically include the desired file based on the user's language selection, I use session variables. For example, if the user selects English, 'en' is stored in the lang variab ...

What methods can I use to locate the circular dependency within my program?

I am facing numerous circular dependency errors in my Angular project, causing it to malfunction. Is there a way to identify the section of the code where these circular dependencies exist? Warning: Circular dependency detected: src\app&bs ...

Horizontal rule located within a table but spanning the entire width

I wrote the following code: <table> {item.awards.map((obj,i) => <tbody> <tr> <td>Name</td> <td>:</td> <td>{obj.title}</td> </tr> ...

At what point are routed components initialized?

Here is a route setup I am working with: path: ':id', component: ViewBookPageComponent }, After adding this route, an error keeps popping up: Error: Cannot read property 'id' of null I haven't included a null check in the compo ...

Ways to extract values from a javascript hash map by exclusively incorporating an array

So here's the issue I'm encountering. Let's consider the following scenario: let surfaces: Map<any, any> = new Map([{"83.1" => Object}, {"84.1" => Object}]) let arr1 = ["83.1"] This is the desired o ...

Allow users to copy and paste on a website where this function is typically restricted

Just wanted to mention that I have very little coding knowledge, so I appreciate your patience. I'm attempting to paste something onto a site that doesn't allow it. Here is the link to the javascript they used to block it: A friend of mine recom ...

Understanding the process of retrieving a data value from HTML in an AngularJS directive

I'm a beginner with Angular and I'm trying to pass some data to my angular directive from the template. <div class="col-md-6" approver-picker="partner.approverPlan.data" data-pickerType="PLAN"></div> I h ...

Error: Element type is invalid: a string was anticipated, but not found

I recently experimented with the example provided in React's documentation at this link and it functioned perfectly. My objective now is to create a button using material-ui. Can you identify what is causing the issue in this code? import * as R ...

Revitalizing HTML and Google Maps with AJAX, PHP, and JQuery

Context: I am currently working on a project that involves integrating a Simple Google Map with an HTML form right below it. The form collects user input and upon submission, sends the data via AJAX to a PHP script for processing API calls and generating i ...