简体   繁体   中英

Filtering nested objects and arrays

I have a Vue project and need to search an array with nested objects for a specific object and then return it. The user has a text input field for searching and the search should target "title".

The data looks like this:

const data = 
[{
    "catId": "1",
    "catTitle": "a",
    "exampleArray": [{
        "id": "111",
        "title": "aaa"
    }, {
        "id": "222",
        "title": "bbb"
    }, {
        "id": "333",
        "title": "ccc"
    }]
}, {
    "catId": "2",
    "catTitle": "b",
    "exampleArray": [{
        "id": "444",
        "title": "ddd"
    }, {
        "id": "555",
        "title": "eee"
    }]
}, {
    "catId": "3",
    "catTitle": "c",
    "exampleArray": []
}, {
    "catId": "4",
    "catTitle": "d",
    "exampleArray": [{
        "id": "555",
        "title": "fff"
    }]
}]

I have tried:


return data.filter(item => {
                    return item.catArray.filter(category=> {
                        return category.title.toLowerCase().includes(this.search.toLowerCase())
                    })
                })

eg if user input is "aaa", should return:


[{
    "catId": "1",
    "catTitle": "a",
    "exampleArray": [{
        "id": "111",
        "title": "aaa"
    }]
}]

The search should also return all matching results.

You were almost there!

 const data = [{ "catId": "1", "catTitle": "a", "exampleArray": [{ "id": "111", "title": "aaa" }, { "id": "222", "title": "bbb" }, { "id": "333", "title": "ccc" }] }, { "catId": "2", "catTitle": "b", "exampleArray": [{ "id": "444", "title": "ddd" }, { "id": "555", "title": "eee" }] }, { "catId": "3", "catTitle": "c", "exampleArray": [] }, { "catId": "4", "catTitle": "d", "exampleArray": [{ "id": "555", "title": "fff" }] }]; const search = "aa"; console.log(data.filter(item => { return item.exampleArray.some(category=> { return category.title.toLowerCase().includes(search.toLowerCase()) }) })); console.log(data.map(item => { item.exampleArray = item.exampleArray.filter(category=> { return category.title.toLowerCase().includes(search.toLowerCase()) }) return item; }).filter(a=>a.exampleArray.length>0))

All I did is add a check for the length after your filter. Because filter expects true or false to know if the element should be included. While it returns an array with results, an empty array is a truthy value. You need to check if the array has elements to filter correctly.

EDIT: I changed to using FIND instead of FILTER. Find will return falsy value if nothing is found, while returning a truthy value (the found element) if something is found. This would have the benefit of not looping through the whole array, stopping as soon as we found something.

EDIT AGAIN: some is the function you want, we learn every day! It does the same as find but instead returns true directly!

You can achieve this requirement with the help of Array.filter() method along with String.includes()

Live Demo :

 const data = [{ "catId": "1", "catTitle": "a", "exampleArray": [{ "id": "111", "title": "aaa" }, { "id": "222", "title": "bbb" }, { "id": "333", "title": "ccc" }] }, { "catId": "2", "catTitle": "b", "exampleArray": [{ "id": "444", "title": "ddd" }, { "id": "555", "title": "eee" }] }, { "catId": "3", "catTitle": "c", "exampleArray": [] }, { "catId": "4", "catTitle": "d", "exampleArray": [{ "id": "555", "title": "fff" }] }]; const searchWord = 'aaa'; const res = data.filter(obj => { obj.exampleArray = obj.exampleArray.filter(({ title }) => title.includes(searchWord)) return obj.exampleArray.length; }); console.log(res);

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