Search through array elements that are nested deeply

Consider the following scenario: an array is provided as input containing various objects with nested elements. The goal is to filter this array in JavaScript and obtain a new array consisting only of objects where the key "navigation" has a value of true.

    [
        {
          "name": "home page",
          "title": "Find Jobs in Technology",
          "url": "https://www.url1.com/",
          "elements": [
            {
              "category": "navigation",
              "buttons": [
                {
                  "title": "Tech Careers",
                  "type": "DropDown",
                  "options": [
                    {
                      "title": "Job Search",
                      "type": "Button",
                      "navigation": true
                    },
                    {
                      "title": "Career Events",
                      "type": "Button",
                      "navigation": false
                    }
                  ]
                },
                {
                  "title": "Insights",
                  "type": "Link",
                  "navigation": true
                }
              ]
            }
          ]
        },
        {
          "name": "tech careers",
          "title": "careers",
          "url": "https://www.url1.com/careers",
          "elements": [
            {
              "category": "navigation",
              "buttons": [
                {
                  "title": "Login",
                  "type": "Link",
                  "navigation": true
                }
              ]
            }
          ]
        }
    ]

The expected result after filtering should be a new array that includes only objects where the "navigation" key is true. See the example below:

[
  {
    "title": "Job Search",
    "type": "Button",
    "navigation": true
  },
  {
    "title": "Insights",
    "type": "Link",
    "navigation": true
  },
  {
    "title": "Login",
    "type": "Link",
    "navigation": true
  }
]

Your assistance in achieving this outcome would be greatly appreciated. Please note that previous attempts using array.filter have not been successful due to limitations when dealing with nested structures.

Answer №1

You have the option to create a filterRecursive function that leverages recursion to filter through nested arrays within objects in the provided input array:

function filterRecursive(hierarchy, predicate) {
    return hierarchy.filter(predicate).concat(
        hierarchy.flatMap(o =>
            Object.values(o).filter(Array.isArray)
                  .flatMap(arr => filterRecursive(arr, predicate))
        )
    );
}

const data = [{"name": "home page","title": "Find Jobs in Technology","url": "https://www.url1.com/","elements": [{"category": "navigation","buttons": [{"title": "Tech Careers","type": "DropDown","options": [{"title": "Job Search","type": "Button","navigation": true},{"title": "Career Events","type": "Button","navigation": false}]},{"title": "Insights","type": "Link","navigation": true}]}]},{"name": "tech careers","title": "careers","url": "https://www.url1.com/careers","elements": [{"category": "navigation","buttons": [{"title": "Login","type": "Link","navigation": true}]}]}];

const result = filterRecursive(data, o => o.navigation === true);
console.log(result);

For a slightly different approach that retains the original order as requested:

function filterRecursive(hierarchy, predicate) {
    return hierarchy.flatMap(o =>
        (predicate(o) ? [o] : []).concat(
            Object.values(o).filter(Array.isArray)
                  .flatMap(arr => filterRecursive(arr, predicate))
        )
    );
}

const data = [{"name": "home page","title": "Find Jobs in Technology","url": "https://www.url1.com/","elements": [{"category": "navigation","buttons": [{"title": "Tech Careers","type": "DropDown","options": [{"title": "Job Search","type": "Button","navigation": true},{"title": "Career Events","type": "Button","navigation": false}]},{"title": "Insights","type": "Link","navigation": true}]}]},{"name": "tech careers","title": "careers","url": "https://www.url1.com/careers","elements": [{"category": "navigation","buttons": [{"title": "Login","type": "Link","navigation": true}]}]}];

const result = filterRecursive(data, o => o.navigation === true);
console.log(result);

Answer №2

Implement a recursive function to filter and store objects that meet certain criteria in a results array:

const arr=[{name:"home page",title:"Find Jobs in Technology",url:"https://www.url1.com/",elements:[{category:"navigation",buttons:[{title:"Tech Careers",type:"DropDown",options:[{title:"Job Search",type:"Button",navigation:true},{title:"Career Events",type:"Button",navigation:false}]},{title:"Insights",type:"Link",navigation:true}]}]},{name:"tech careers",title:"careers",url:"https://www.url1.com/careers",elements:[{category:"navigation",buttons:[{title:"Login",type:"Link",navigation:true}]}]}]

const res = []

function findNavTrue(arr) {
  arr.forEach(obj => {
    for (let [key, val] of Object.entries(obj)) {
      if (Array.isArray(val)) {
        findNavTrue(val)
      } else if (key === "navigation" && val === true) {
        res.push(obj)
      }
    }
  })
}

findNavTrue(arr)
console.log(res)

Answer №3

Make sure to review the following:


let arr = [{
    name: "home page",
    title: "Find Jobs in Technology",
    url: "https://www.url1.com/",
    elements: [{
        category: "navigation",
        buttons: [{
                title: "Tech Careers",
                type: "DropDown",
                options: [{
                        title: "Job Search",
                        type: "Button",
                        navigation: true
                    },
                    {
                        title: "Career Events",
                        type: "Button",
                        navigation: false
                    }
                ]
            },
            {
                title: "Insights",
                type: "Link",
                navigation: true
            }
        ]
    }]
}, {
    name: "tech careers",
    title: "careers",
    url: "https://www.url1.com/careers",
    elements: [{
        category: "navigation",
        buttons: [{
            title: "Login",
            type: "Link",
            navigation: true
        }]
    }]
}]

let nav = [];
arr.map((elem1) => {
    elem1.elements.map((elem2) => {
        elem2.buttons.map((elem3) => {
            if (elem3.type == 'DropDown') {
                elem3.options.map((elem4) => {
                    if (elem4.navigation) nav.push(elem4)
                })
            } else if (elem3.navigation) nav.push(elem3)
        })
    })
})
console.log(nav);

Answer №4

I prefer implementing nested forEach loops

It may not be as efficient as a recursive approach, but it definitely enhances readability

function filterData(array) {
  const filteredArray = [];

  array.forEach(page => {
    page.elements.forEach(el => {
      el.buttons.forEach(btn => {
        if (btn?.type === "DropDown") {
          btn.options.forEach(opt => {
            if (opt.navigation === true) {
              filteredArray.push(opt);
            }
          });
        } else if (btn.navigation === true) {
          filteredArray.push(btn);
        }
      })
    })
  });

  return filteredArray;
}

const websiteData = [{"name": "home page","title": "Find Jobs in Technology","url": "https://www.url1.com/","elements": [{"category": "navigation","buttons": [{"title": "Tech Careers","type": "DropDown","options": [{"title": "Job Search","type": "Button","navigation": true},{"title": "Career Events","type": "Button","navigation": false}]},{"title": "Insights","type": "Link","navigation": true}]}]},{"name": "tech careers","title": "careers","url": "https://www.url1.com/careers","elements": [{"category": "navigation","buttons": [{"title": "Login","type": "Link","navigation": true}]}]}];

console.log(filterData(websiteData));

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

Toggle the on and off functionality of a button using ajax response for content display

I'm struggling to figure out why the button isn't working for me. I am familiar with how to enable and disable buttons using attr and prop. $(document).on("click", "#btn", function(){ $(this).html("Sending..."); $(this).prop("disabl ...

Triggering transitionend event once with an added if condition

Currently, I have an application of an if statement that examines whether an element contains a style attribute. In the event that the style attribute is absent, it appends inline styling. Conversely, if the style attribute exists, it is removed. Furthermo ...

How can we incorporate spans into child elements using JavaScript?

Recently, I encountered a problem with a code that is supposed to add a span if it doesn't already exist on certain elements. However, the current implementation only adds the span to one element and not others because the code detects that it already ...

Problem encountered when attempting to post to a node/express endpoint

It has been a while since I last used JQuery/Ajax instead of axios to connect to an endpoint, am i making any mistakes here? var express = require('express'); var app = express() var bodyParser = require('body-parser'); var path = re ...

Issue with PHP array function is that it is only showing the first element in the array while disregarding the rest

Having an issue with displaying multiple client's items in an array. My current code only shows the first item id in the array. Can you help me identify what I'm doing wrong? Check out this example of sItem value: $items = array(); $cli ...

URL validation RegEx in AngularJs using Javascript

I am looking for the following URLs to return as true other.some.url some.url some.url/page/1 The following URL should be flagged as false somerandomvalue Here is the regex I have been experimenting with so far: /^(?:http(s)?:\/\/) ...

Retrieving ng-repeat object in Angular

How can I retrieve the current object from an ng-repeat on ng-click without using $index? The $index method is giving me the wrong index due to my use of orderBy. Ideally, I would like to be able to click on the object (thumbnail) and have $scope.activePer ...

Is it appropriate to refer to a single page application as a web 3.0 application?

As time progresses, we are witnessing the rise of more and more single page applications or frameworks such as new twitter and Sammy. It appears to be a significant advancement where we move away from generating code on the server side, with servers actin ...

Tips for passing multiple values with the same key in Axios as parameters

I need to develop a function that allows users to select multiple categories and subcategories, then send their corresponding ids as a query string using Axios. For example, if a user selects category IDs 1 and 2, along with subcategory IDs 31 and 65, the ...

What causes the error of inputRef.current being null in CurrencyTextField?

When attempting to target the second 'CurrentTextField' after changing the value of the first 'CurrentTextField', an error occurs stating 'inputRef.current is null'. import React, {useRef } from 'react'; import Curr ...

I am unable to generate a vite application within WSL

My system is running node version 10.19.0 and npm version 6.14.4. Whenever I try to run create-vite@latest client, I encounter the following error: npx: installed 1 in 0.79s /home/victor/.npm/_npx/86414/lib/node_modules/create-vite/index.js:3 import &apos ...

The EJS file is failing to display the stylesheet even though it is being pulled from the

Encountering a strange issue where the page routed to display additional information about a specific record from my database list on the homepage is not loading the stylesheets located in my partial/head, despite successfully passing the object informatio ...

JavaScript will continue to process the submit to the server even after validation has been completed

My current challenge involves implementing form validation using JavaScript. The goal is to prevent the form from being sent to the server if any errors are found. I have made sure that my JavaScript function returns false in case of an error, like so: ...

Setting up PostgreSQL database integration with Node.js

I want to remove certain entries from a PostgreSQL database based on creation/expiry dates, but I only want this to happen when the Node server first starts. Currently, I have added the line DELETE FROM ....db WHERE date <= CURRENT_DATE to the main r ...

What is the solution to having a div move along with window resizing without displacing adjacent divs?

After much effort, I still can't seem to get this working correctly. I've been playing around with a section named "RightExtra" and a div inside it called "RightExtraContent". My goal is to allow these two divs to move freely when the window is ...

establishing the dimensions of table data cells

I'm facing a challenge with setting the width and height for table data that changes dynamically based on different values. The dimensions of the table itself are not definite, so I need to find a solution. Here's the code snippet I'm curren ...

Dismiss the Popover in Ionic 2

After opening a popover that redirects me to another page and then returning to the root page (popToRoot), I reload the data/dom upon an event and dismiss the popup once the json data is received from the server. Everything works smoothly with a lengthy ti ...

Local Storage State Persistence Issue with React Checkbox Component

I am currently working on a React component that features a checkbox. My goal is to have the checkbox toggle between on and off states and save this state in local storage so that even when navigating to another page, the toggle will remain in its previous ...

Tips for inserting an array into a text box using Python and Selenium scripting

I have a code written to input an array list into a text-box on my internal site. The array values are coming from an excel sheet. value = [] // ArrayList while len(value)<1000: Data=sheet.row(loop) T1 = Data[1].value T2=int(T1) // to remov ...

Removing a single object from an array of objects using MongooseJS

Hello to all the MongooseJS experts out there! I'm a newcomer to MongooseJS, and I've been trying to solve this problem for the past two days but haven't found a solution yet. Thank you in advance for any help! The Issue with My Delete me ...