Reputation: 1257
I have a list with a child list (see example JSON below), where a value inside the child list is be searchable in the UI.
When console logging, it finds the matches, but the returned data is not filtered (aka : includes all data)
It must be my knowledge of filter functions which is a bit limited, and i have understood it wrong. Can someone correct me here ?
Example JSON :
{
"id": "fb18eee6-423e-475d-9077-c03dd4ffd80f",
"text": "Hvor lang holdbarhet har kyllingfilet i fryseren?",
"intent": "shelf_life",
"entities": [
{
"start": 25,
"end": 37,
"value": "kyllingfilet",
"entity": "ingredient"
},
{
"start": 40,
"end": 48,
"value": "fryseren",
"entity": "ingredient_placement"
},
{
"start": 10,
"end": 20,
"value": "holdbarhet",
"entity": "shelf_life"
}
],
"isSociety": false
},
{
"id": "1072392a-38dc-43f2-affe-74a4fde81bfd",
"text": "Hvor lang holdbarhet har ribbe i kjøleskapet? ",
"intent": "shelf_life",
"entities": [
{
"start": 33,
"end": 44,
"value": "kjøleskapet",
"entity": "ingredient_placement"
},
{
"start": 10,
"end": 20,
"value": "holdbarhet",
"entity": "shelf_life"
},
{
"start": 25,
"end": 30,
"value": "ribbe",
"entity": "ingredient"
}
],
"isSociety": false
}
Here is the filter code :
let searchstring = this.searchtext;
let filtered = this.nluDataUnfiltered.filter(intent => {
return intent.entities.filter(entity => {
return entity.value.toLowerCase().indexOf(searchstring.toLowerCase()) > -1
// if (entity.value.toLowerCase() === searchstring.toLowerCase()){
// console.log("matched : " + entity.value + " <-> " + searchstring)
// PS ! When a match is found, it console logs it out (works!)
// }
})
});
return filtered;
Upvotes: 1
Views: 1778
Reputation: 162
The nested filter expression (the one that returns entity.value.toLowerCase()
), etc. returns all values that pass the boolean test, this is the correct way to use filter expressions in javascript. So essentially, you pass a boolean test to the filter and the filter returns all items that pass this test. In your outer filter function however, that's not what you are doing. After the nested filter has returned, your outer filter function should take as an argument another boolean expression that returns either true or false. But, as both Zerkms and Zze pointed out already, in your case you provide it with an array of items, or here, with an array containing only a single item - the item that passed the previous boolean expression. You need to transform the expression in your outer filter to become a boolean expression, so maybe do something like this:
let filtered = nluDataUnfiltered.filter(intent => {
return intent.entities.includes(...intent.entities.filter(entity => {
return entity.value.toLowerCase().indexOf(searchstring.toLowerCase()) > -1
}))
})
That way the includes() method will check whether or not the entities array includes the entity that was searched for and will finally return all intent objects that pass this test. I use the javascript ...
spread operator to transform the returned array into single items because otherwise you'll pass an array to the include method rather than the single item as is intended here.
Upvotes: 1