0

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())
                    })
                })

e.g. if user input is "aaa", should return:


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

The search should also return all matching results.

2 Answers 2

1

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!

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

7 Comments

On a side note, instead of filter/some you could have used find, thinking about it I think it would be best.
I'd suggest to use some instead of the nested filter(...).length > 0. It has the same effect, but is more concise and efficient
Oh you're right... Reading about it just now, never really used it I really tought it was an alias for filter! Thanks
Thanks, this got me much closer to desired result. Only problem still is that if search term is e.g. 'aa' , I get all of these as a result from exampleArray: [{"id": "111", "title": "aaa"}, { "id": "222", "title": "bbb"}, {"id": "333", "title": "ccc"}] Where the expected outcome is only: [{"id": "111","title": "aaa"}]
I did not understand it that way, I have edited the code snippet to add a new console log to have the behaviour you ask. What I did is filter all "exampleArray" elements on the requested search string and then filter all elements that have empty "exampleArray"
|
0

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

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.