I have a vue project and need to search an array with nested objects for a specific object and then return it. User has a text input field for searching and search should target "title".
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"
}]
}]
Search should also return all matching results.
CodePudding user response:
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 = "fff";
console.log(data.filter(item => {
return item.exampleArray.some(category=> {
return category.title.toLowerCase().includes(search.toLowerCase())
})
}))
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!
CodePudding user response:
To search an array of objects for a specific object and return it, you can use the Array.prototype.find()
method. The find() method takes a callback function that returns a boolean value indicating whether the object should be included in the result.
Here is an example of how you could use the find() method to search the data array for a specific object and return it:
const data = [
{
catId: "1",
catTitle: "a",
exampleArray: [
{
id: "111",
title: "aaa",
},
{
id: "222",
title: "bbb",
},
{
id: "333",
title: "ccc",
},
],
},
// ...
];
// The search term that the user entered
const searchTerm = "aaa";
// Use the find() method to search the data array for the object that has
// a title property that includes the search term
const result = data.find((item) => {
return item.exampleArray.some((item) => {
return item.title.toLowerCase().includes(searchTerm.toLowerCase());
});
});
console.log(result);
// The result will be:
// {
// "catId": "1",
// "catTitle": "a",
// "exampleArray": [{
// "id": "111",
// "title": "aaa"
// }]
// }
In this code, the find() method is used to search the data array for the object that has a title property that includes the search term (which is converted to lowercase before being compared to the title property to make the search case-insensitive).
The Array.prototype.some() method is used inside the callback function passed to find() to check if any of the objects in the exampleArray property have a title property that includes the search term.
If the search term is found in one of the title properties, the find() method will return the object that contains it. Otherwise, it will return undefined.
CodePudding user response:
Here is one way you can accomplish this:
return data.Filter(item => {
// filter the `exampleArray` for each `item` by checking if the `title` property of each object in the array contains the search string
const matchingItems = item.exampleArray.filter(example => example.title.toLowerCase().includes(this.search.toLowerCase()));
// return `true` for the current `item` if there are any matching items in the `exampleArray`
return matchingItems.length > 0;
});
This code will filter the data array to only include objects where at least one object in the exampleArray
has a title property that contains the search string. It will also return only the matching objects in the exampleArray
for each item.
If the search string is "aaa", this will return the following array:
[
{
"catId":"1",
"catTitle":"a",
"exampleArray":[
{
"id":"111",
"title":"aaa"
}
]
}
]
CodePudding user response:
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);