Strategies for effectively searching and filtering nested arrays

I'm facing a challenge with filtering an array of objects based on a nested property and a search term.

Here is a sample array:

let items = [
  {
    category: 15,
    label: "Components",
    value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
    children: [
      {
        category: 1,
        label: "Carousel1",
        diId: 55946,
        // More nested objects here
        children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
        value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
      },
      {
        category: 2,
        label: "Checkbox1",
        diId: 193909,
        children: [{ label: "datafound", value: "47d18sb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
        value: "045e8786-2165-4e1e-a839-99b1b0ceef57"
      }
    ]
  },
  {
    value: "4be22726-850c-4905-ab3b-039fcf607d55",
    label: "Default",
    children: [
      {
        category: 5,
        defaultValueType: 1,
        label: "Empty",
        toType: "String",
        value: "ebedb43f-4c53-491f-8954-d030321845cd"
      },
      // More entries here
    ]
  },
  {
    category: 4,
    label: "Fixed Value",
    isFixed: true,
    value: "28e90e3e-a20b-4499-9593-061a7d1e7bd6"
  }
]};

The goal is to filter the array based on a specific search term, like 'nodata' or 'spa'.

If searching for 'nodata', the filtered result should be:

let items = [
  {
    category: 15,
    label: "Components",
    value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
    children: [
      {
        category: 1,
        label: "Carousel1",
        diId: 55946,
        children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
        value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
      }
    ]
  }
];

For a search term like 'spa', the expected output would be:

let items = [
  {
    value: "4be22726-850c-4905-ab3b-039fcf607d55",
    label: "Default",
    children: [
      {
        category: 5,
        defaultValueType: 2,
        label: "Space",
        toType: "String",
        value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
      }
    ]
  }
];

I appreciate any assistance in solving this issue. Thank you!

Answer №1

If you're looking for a solution, the following function is tailored just for you:

function performSearch(dataArray, keyword) {
  return dataArray.flatMap(obj => {
    const hasKeyword = Object.entries(obj)
      .some(([key, value]) => key !== 'children' && String(value).toLowerCase().includes(keyword.toLowerCase()));
    
    if (hasKeyword && !obj.children) return [obj];
    
    const matchedChildren = performSearch(obj.children ?? [], keyword);
    return hasKeyword || matchedChildren.length > 0
      ? [{
        ...obj,
        children: matchedChildren,
      }]
      : [];
  })
}

The function works recursively to scan through the data array, identifying entries that contain the specified keyword and incorporating them into a new object. It maintains the nested structure of the original object, which may or may not be suitable for your requirements. Feel free to adjust the algorithm to better suit your needs.

let allData = [
  {
    category: 15,
    label: "Components",
    value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
    children: [
      {
        category: 1,
        label: "Carousel1",
        diId: 55946,
        // numerous nested children arrays of objects are present
        children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
        value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
      },
      {
        category: 2,
        label: "Checkbox1",
        diId: 193909,
        children: [{ label: "datafound", value: "47d18sb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
        value: "045e8786-2165-4e1e-a839-99b1b0ceef57"
      }
    ]
  },
  {
    value: "4be22726-850c-4905-ab3b-039fcf607d55",
    label: "Default",
    children: [
      {
        category: 5,
        defaultValueType: 1,
        label: "Empty",
        toType: "String",
        value: "ebedb43f-4c53-491f-8954-d030321845cd"
      },
      {
        category: 5,
        defaultValueType: 2,
        label: "Space",
        toType: "String",
        value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
      },
      {
        category: 5,
        defaultValueType: 8,
        label: "Current Username",
        toType: "String",
        value: "25f6b40a-33c7-4f17-b29d-99e8d1e4e33c"
      },
      {
        category: 5,
        defaultValueType: 9,
        label: "Current Location",
        toType: "Location",
        value: "ed59da2f-318d-4599-9085-4d9d769a27d7"
      }
    ]
  },
  {
    category: 4,
    label: "Fixed Value",
    isFixed: true,
    value: "28e90e3e-a20b-4499-9593-061a7d1e7bd6"
    // no children exist in this object
  }
];



function performSearch(dataArray, keyword) {
  return dataArray.flatMap(obj => {
    const hasKeyword = Object.entries(obj)
      .some(([key, value]) => key !== 'children' && String(value).toLowerCase().includes(keyword.toLowerCase()));
    
    if (hasKeyword && !obj.children) return [obj];
    
    const matchedChildren = performSearch(obj.children ?? [], keyword);
    return hasKeyword || matchedChildren.length > 0
      ? [{
        ...obj,
        children: matchedChildren,
      }]
      : [];
  })
}

console.log('----- Search: nodata')
console.log(JSON.stringify(performSearch(allData, 'nodata'), null, 2))
console.log('----- Search: spa')
console.log(JSON.stringify(performSearch(allData, 'spa'), null, 2))

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

What is preventing me from being able to manipulate the data retrieved from this ajax request?

I've been attempting to make an ajax call to my json server on localhost:3000 in order to retrieve an object that I can manipulate and display on a webpage. However, no matter what I try, I just can't seem to console log the (data) so that I can ...

Creating a counter while iterating over a JSON array in jq

I am currently working with jq-1.5. My goal is to generate a running counter (index) for a JSON array. The JSON data I have is: {"Actors": "Tom,Dick,Mary"} To split the string into an array, I am using splits(): echo '{"Actors": "Tom,Dick,Mary"}&a ...

Efficiently refine your search using the combination of checkboxes and dropdown menus simultaneously

I am currently in the process of creating a highly sortable and filterable image gallery that utilizes numerous tags. The inspiration for this project stems from a similar question on Stack Overflow regarding dropdown menus and checkboxes. You can view the ...

Maintain the original order of rows in the table while shuffling the columns they appear in randomly

I need help with my table setup. The left column contains words in English, while the right column has the same words translated into Korean. Is there a way to keep the rows intact while randomizing the order of the columns? Here's an example: <ta ...

After closing, the position of the qtip2 is being altered

I've successfully integrated the qtip2 with fullcalendar jQuery plugin, which are both amazing tools. However, I'm encountering an issue with the positioning of the qtip. Here's the code snippet I'm using: $(window).load(function() { ...

Whenever I declare it, the onclick method is executed

I have been attempting to define an onclick method that would trigger a function to clear and reconstruct the display, revealing more detailed information about the clicked item. However, I am facing an issue where the assigned onclick method is executed i ...

Tips for executing mocha tests using a reporter

Whenever I execute the command npm test, it displays this output: mocha ./tests/ --recursive --reporter mocha-junit-reporter All the tests are executed successfully. However, when I attempt to run mocha with ./tests/flickr/mytest --reporter junit-report ...

Automating the deployment of a vue.js app using GitLab CI/CD pipeline to deploy to

Currently experiencing an issue with the pipelines involving my YAML file that automates deployment of a Vue app to Firebase. Despite including scripts in the file and setting up the Environment variable FIREBASE_TOKEN on GitLab, pushing the code to a GitL ...

Ways to retrieve a Class Level Variable within the onCellValueChanged function in agGrid

Exploring Angular with Typescript for the first time. I'm trying to access Class Level Variables within the onCellValueChanged event of agGrid, but encountering the following error: Cannot read property 'updateDict' of undefined Here&apo ...

Manipulating data in PHP with the help of JSON: Adding an array into a nested array

I am currently working on creating a JSON structure that needs to be sent back to Ajax. My goal is to include the key-value pair of 'para' => "Hello" inside the "content" section as shown below: { "sections": { "content": [{ ...

Guide on dynamically displaying a page based on the response from express/mssql middleware

I have developed a full stack application that includes a registration feature which successfully adds data to the database. Now, I am looking for a way to conditionally display the home page based on whether the login credentials are correct. Within my l ...

What is the most effective method for transferring resolved promise values to a subsequent "then" chain?

Currently, I am grappling with understanding promises by utilizing the Q module in node.js. However, I have encountered a minor setback. Consider this scenario: ModelA.create(/* params */) .then(function(modelA){ return ModelB.create(/* params */); } ...

Creating identical class names for UL elements underneath LI using JavaScript

In my attempt to dynamically generate the class name within the ul element, I successfully achieved the expected result. The outcome can be viewed in the console of the snippet provided for reference. However, I'm facing a challenge when attempting t ...

creating an identical copy of a dynamic element's size

I am currently working on a project using react js where I need to incorporate multiple images. My goal is to have standard background divs / rectangles that match the exact size of each image, allowing for animations to be performed on top of them. The sn ...

Using Styled Components to achieve full width for input tag in relation to its parent

I am working with an input field that has a specific width set. My goal is to increase the width of this input field to 100% by selecting it from its parent component. Is there a way to achieve this without passing an explicit width prop in the styled c ...

Identifying Changes in Form Values Using jQuery

I am facing a challenge with a dynamic form that needs to detect the field sequence properly. Below is my JavaScript file: var i = 1; $("a.add-line").click(function(){ $("div.items").append( $('<div>').attr('id',&ap ...

Having trouble assigning more than one custom named property in TypeScript for MUI v5 Palette

I am currently setting up multiple custom attributes to make future updates easier. Nonetheless, I'm encountering a challenge with implementing more than one custom property in MUI v5. TypeScript Error TS2717: Subsequent property declarations must hav ...

The .angular-cli.json file is causing issues with loading scripts

I have recently updated my .angular-cli.json file by adding new scripts in the following format: "apps": [ { "root": "src", "outDir": "dist", "assets": [ "assets", "favicon.ico" ], "index": "index.html ...

Swapping out nodes for images using d3.js

Below is the code snippet I am currently executing http://jsfiddle.net/a7as6/14/ I have implemented the following code to convert a node to an image: node.append("svg:image") .attr("class", "circle") .attr("xlink:href", "https://github.com/favico ...

Illustration of a D3 graph demo

I'm currently working on modifying a d3.js graph example originally created by Mike Bostock. My goal is to replace the d3.csv method with d3.json. I made adjustments to parts of the original code, but unfortunately, my graph has disappeared without an ...