I was trying to search for function. This function checks the nested array, which has multiple strings, then returns if the array has a search word.
The data structure of the array
[
{
name:'aa',
searchWords:['aa','ab','bc'] <- I want to use this array for search
},
{
name:'bb',
searchWords:['bb','bc','de'] <- I want to use this array for search
},
...
]
I tried to use indexOf function.
However, I couldn't display any components with this code below.
But I changed target value from item.searchWords to item.name in the code. it worked.
HTML
<div className="itemWrapper">
{filterItems.map((item, idx) => (
<Item key={idx} {...item} id={idx} list={list} />
))}
</div>
Js
const filterItems = list.filter(
(item) => item.searchWords.indexOf(searchWord) !== -1,
);
My desired result is that search result update in realtime.
For instance with the same data structure above, when the user searches 'a', searchWords 'aa' and 'ab' returns true for displaying the item,
Thank you so much for your help.
You need to loop over the searchWords array to find if it matches the search word. This one will workconst filterItems = list.filter( (item) => item.searchWords.filter((myWord) => myWord.indexOf(searchWord)>-1) );
You can try with find()
and includes()
on name property of the object and finally filter()
.
Demo:
var list = [ { name:'aa', searchWords:['aa','ab','bc'] }, { name:'bb', searchWords:['bb','bc','de'] } ] document.getElementById('searchWord').addEventListener('input', function(){ console.clear(); var filterItems = list.find(item => item.name.includes(this.value)); filterItems = filterItems? filterItems.searchWords: []; filterItems = filterItems.filter(i => i.includes(this.value)); console.log(filterItems); });
<input id="searchWord"/>
You can use array#reduce
and filter searchWords
array using the array#filter
by checking the search words.
const dataSource = [{ name: 'aa', searchWords: ['aa', 'ab', 'bc'] }, { name: 'bb', searchWords: ['bb', 'bc', 'de'] } ], searchWord = 'a', result = dataSource.reduce((res, {name, searchWords}) => { let matched = searchWords.filter(word => word.includes(searchWord)); if(matched.length) { res.push({name, searchWords: matched}); } return res; },[]) console.log(result);
It is because, how indexOf
works, with array
and strings
.
let's say syntax of indexOf is
operatedItem.indexOf(searchedItem);
Here, in your case
{
name:'bb',
searchWords:['bb','bc','de']
}
name is a string ,
and searchWords is an array .
When you perform:
name.indexOf("b"); //0
name.indexOf("bb"); //0
name.indexOf("a"); //-1
It will check if the searchedItem
exists anywhere in operatedItem
.
let str = "aa ab a bb"; console.log(str.indexOf("a")); //0 console.log(str.indexOf("aa")); //0 console.log(str.indexOf("ab")); //3 console.log(str.indexOf("b")); //4 console.log(str.indexOf("c")); //-1 console.log(str.indexOf("aaa")); //-1
And when indexOf is used with array ,
it checks if a searchedItem
exists in the operatedItem
array, it will not go for substring search.
let arr = ["aa", "ab", "a", "bb"]; console.log(arr.indexOf("a")); //2 console.log(arr.indexOf("aa")); //0 console.log(arr.indexOf("ab")); //1 console.log(arr.indexOf("b")); //-1 console.log(arr.indexOf("c")); //-1 console.log(arr.indexOf("aaa")); //-1
The issue with the code is that its trying to find if the array contains a word when you use indexOf. Eg: When you search for 'a', the code checks is there is any word 'a' in the array and not any word containing letter 'a'.
You need to change the JS part to:
Js
const list = [{ name: 'aa', searchWords: ['aa', 'ab', 'bc'] }, { name: 'bb', searchWords: ['bb', 'bc', 'de'] } ]; let searchWord = "a"; const filterItems = list.filter( (item) => item.searchWords.filter(word => word.includes(searchWord)).length > 0 ); document.getElementById('result').innerHTML = JSON.stringify(filterItems);
<p id="result"> </>
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.