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.
CodePudding user response:
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);
CodePudding user response:
I wrote it for 5 minutes, I would use nested forEach
It's not that smart, but more readable
function filter(array) {
const filteredArray = [];
array.forEach(page => {
page.elements.forEach(el => {
el.buttons.forEach(btn => {
// if button contains the navigation prop
if (btn?.navigation === true) {
filteredArray.push(btn);
return;
}
// else button contains other options
btn.options.forEach(opt => {
if (opt.navigation === true) {
filteredArray.push(opt);
}
});
})
})
});
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));
CodePudding user response:
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)
CodePudding user response:
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);