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

Exploring JSON data with ReactJS

I am experiencing issues with populating a table with data imported from a JSON file. The error message I'm receiving is: Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {list}). If you intended to render ...

Tips for verifying an alphanumeric email address

I need to create an email validation script that allows only alphanumeric characters. <script type = "text/javascript"> function checkField(email) { if (/[^0-9a-bA-B\s]/gi.test(email.value)) { alert ("Only alphanumeric characters and spaces are ...

Identifying the presence of an image in a directory and displaying a standard image if not found

I have a directory containing pictures of different wines, each labeled with a specific code (e.g. FMP-HTR17). I would like to show the corresponding picture if it is available, but display a default image if the specific picture does not exist in the dire ...

Potential bug may arise with the hashchange event

Recently, I stumbled upon a rather unique bug in my Javascript code that has left me puzzled. Here's the scenario: within a parent div with relative positioning, there are three child divs positioned absolutely side by side. Each child div is 1200px ...

What are the possible complications that could arise from implementing this system for designing web pages?

Feeling frustrated with the limitations and compatibility issues of CSS, I decided to create a new approach for structuring webpages. Instead of relying on CSS, I developed a javascript library that reads layout instructions from XML files and uses absolut ...

Sinon's fakeTimers failing to trigger

I'm encountering an issue with sinon's fakeTimers while working in a setup that includes Marionette.js, underscore, and chai test runner. Strangely, when I place a breakpoint in Chrome and step through the code, my timer functions as expected. Ho ...

Dynamic styling updates on page refresh in Next.js

There is a strange issue with my styling that I can't seem to figure out. I have a NavBar set to be 20vh in height and an image set to be 100% in width. However, whenever I refresh the page, the NavBar height decreases and the image width increases si ...

Is your Phonegap and Jquery app experiencing delays in script loading?

I recently developed a phonegap + JQM application and encountered an issue with the loading time of external JavaScript files. To elaborate, when the app starts, the initial file that appears is loader.html. In this file, I have included several JS files ...

Retrieve particular JSON information on a single webpage by selecting an element on a separate page

My goal is to fetch specific information from a JSON file and display it on different HTML pages by clicking a button. I will achieve this using jQuery and plain JS. For the first HTML page, I want to show all products from the JSON in an element with id= ...

What could be causing the "AJAX data not defined" error

Attempting to make an Ajax post request to the root directory on my Express server. By simply using the HTML form and submitting an artist name, I successfully receive a response back and can send the information to the client without any issues... As se ...

What steps should be taken to properly assess an AngularJS provider setup?

My provider definition looks like this: (function(angular) { angular.module('myModule', []) .provider('myService', function () { var service = {}; service.configureSomething = function () { }; service.$get = function () { ...

Enhancing HTML "range" element with mouse scroll functionality for incrementing values in step increments

I'm working on developing a scroll feature that operates independently from the main window's scrolling function. I aim to trigger specific events in the primary window based on interactions with this separate scrollbar. The only solution I coul ...

jQuery import children into output

When inserting a div every nth-child and later calling the children of the parent, the jQuery inserted elements do not appear in this new list. How can I retrieve the inserted elements as well? Apologies if this is confusing. If it's easier to under ...

Stop jQuery function from activating twice during scrolling

I'm looking for a solution to optimize my code that detects if an element is in the viewport and triggers certain actions. Currently, it re-runs the code every time a scroll event occurs when the element is above the fold. Is there a way to make it on ...

Dynamically access nested objects by utilizing an array of strings as a pathway

Struggling to find a solution for accessing nested object properties dynamically? The property path needs to be represented as an array of strings. For example, to retrieve the label, use ['type', 'label'] I'm at a roadblock wit ...

Utilizing URL-based conditions in Reactjs

Currently, I am working with Reactjs and utilizing the Next.js framework. My goal is to display different text depending on whether the URL contains "?id=pinned". How can I achieve this? Below is the snippet of my code located in [slug.js] return( ...

Display or conceal a <div> segment based on the drop down selection made

A dropdown menu controls the visibility of certain div elements based on the selection made. While this functionality is working for one dropdown, it's not working for another even though the code is very similar. I've tried various solutions but ...

Retrieve the entity object and convert it into JSON format using json_encode

I have an array that looks something like this: $general_informations['company'] = $company_db In this array, $company_db is an Entity object with properties, such as: $city = $company_db->getCity(); After using json_encode(), I want to re ...

Glitch found in Safari involving innerText of elements

Hey everyone, I posted this question not too long ago but now I have some images to share regarding the issue with Safari. When checking the console in Safari, the following text is displayed: <div id="rot3posDisp" class="rotDisp">C</div> Ho ...

Differences between the http module and Express framework

After noticing this common pattern, I've become intrigued : const server = http.createServer(app); // Listen on provided port, on all network interfaces. server.listen(port); server.on('error', onError); server.on('listening', on ...