0

Given: an array

    [
        {
          "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
                }
              ]
            }
          ]
        }
    ]

I would like to filter this array using Javascript to get an array of objects with "navigation": true.

Expected filtered array:

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

Thanks in advance.

I tried array.filter, but it works for one level of items.

4 Answers 4

3

You could make a filterRecursive function that uses recursion to filter in deeper arrays inside the objects in the given 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);

Here is a small variant, that produces the results in the order that you have in the question:

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);

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

4 Comments

Based on the expected result, the OP is probably not looking for a DFS algorithm.
@AngelPolitis, actually the order in the question is what DFS would produce if it were pre-order. I added a second recursive function that produces that order.
Scratch that not 😄
You can also scratch the remark ;-)
0

Use a recursive function and add objects to a results array if the key/value pair of the object match the criteria:

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)

Comments

0

Please check it:

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);

1 Comment

I would use forEach in this case instead of map because map returns an array, when forEach iterates it and returns nothing
0

I would use nested forEach

It's not that smart as recursive method, but more readable

function filter(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 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}]}]}];

console.log(filter(data));

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.