简体   繁体   中英

Filter array of objects based on criteria in another array of objects

I want to filter items from the categories array based on the criteria in the otherCategories array.

If otherCategories contains an object where title matches one title from categories.subCategory[i].title and name matches categories.subCategory[i].details.name , then filter only that object eg "item1" from categories .

var categories = [
{
    title:"item1",
    subCategory:[
        {
            title:"subCat1",
            details:{
                name:"detail1",
                email:"test@test.com"
            }
        },
        {
            title:"subCat2",
            details:{
                name:"detail2",
                email:"test@test.com"
            }
        }
    ]
},
{
    title:"item2",
    subCategory:[
        {
            title:"subCat1",
            details:{
                name:"detail3",
                email:"test@test.com"
            }
        },
        {
            title:"subCat2",
            details:{
                name:"detail2",
                email:"test@test.com"
            }
        }
    ]
}
]

var otherCategories = [
{
    title:"subCat1",
    name:"detail1"        
}
]

Expected result

categories = [
{
    title:"item1",
    subCategory:[
        {
            title:"subCat1",
            details:{
                name:"detail1",
                email:"test@test.com"
            }
        },
        {
            title:"subCat2",
            details:{
                name:"detail2",
                email:"test@test.com"
            }
        }
    ]
}]

Use Array.reduce , Array.filter & Array.some

  • Convert the otherCategories array to an object with title as key and name as value
  • Filter categories array where some subCategory exists with matching values

 var categories = [{title:"item1",subCategory:[{title:"subCat1",details:{name:"detail1",email:"test@test.com"}},{title:"subCat2",details:{name:"detail2",email:"test@test.com"}}]},{title:"item2",subCategory:[{title:"subCat1",details:{name:"detail3",email:"test@test.com"}},{title:"subCat2",details:{name:"detail2",email:"test@test.com"}}]}]; var otherCategories = [{title:"subCat1",name:"detail1"}]; var obj = otherCategories.reduce((a,c) => Object.assign(a,{[c.title]:c.name}), {}); categories = categories.filter(v => v.subCategory.some(o => obj[o.title] === o.details.name)); console.log(categories); 

Another approach that will usually work for simple objects like the ones in your example, is to convert your otherCategories array to an array of "stringified" objects, and then filter categories by comparing "stringified" versions of the desired subCategory key value pairs to the converted otherCategories array.

Important to note, however, that object property order is not guaranteed in JavaScript (although many browsers will preserve property order). That means that this approach may not work in some situations and an approach like the one suggested by @NikhilAggarwal is more stable.

For example:

 const categories = [{title: "item1", subCategory: [{title: "subCat1", details: {name: "detail1", email: "test@test.com"}},{title: "subCat2", details: {name: "detail2", email: "test@test.com"}}]}, {title: "item2", subCategory: [{title: "subCat1", details: {name: "detail3", email: "test@test.com"}},{title: "subCat2", details: {name: "detail2", email: "test@test.com"}}]}]; const otherCategories = [{title: "subCat1", name: "detail1"}]; let matches = otherCategories.map((item) => JSON.stringify(item)); let results = categories.filter((item) => { for (let sub of item.subCategory) { let match = JSON.stringify({title: sub.title, name: sub.details.name}); if (matches.includes(match)) { return item; } } }); console.log(results); 

You could map the categories to the results by filtering the subCategories:

  function matches(sub, filters) {
    return filters.some(filter => filter.title === sub.title && filter.name === sub.name);
 }

 const result = categories.map(({ title, subCategories }) => ({ title, subCategories: subCategories.filter(sub => matches(sub, otherCategories)) }));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM