I have the following code in Angular. I want to be able to find "north america" by typing "america north". How do I do that?
const getContinents = keys =>
[
'africa',
'antarctica',
'asia',
'australia',
'europe',
'north america',
'south america'
].filter(e => e.indexOf(keys.toLowerCase()) > -1);
const fakeContinentsRequest = keys =>
of(getContinents(keys)).pipe(
tap(_ => console.log(`API CALL at ${new Date()}`))
);
fromEvent(document.getElementById('type-ahead'), 'keyup')
.pipe(
debounceTime(200),
map((e: any) => e.target.value),
distinctUntilChanged(),
switchMap(fakeContinentsRequest),
tap(c => (document.getElementById('output').innerText = c.join('\n')))
)
.subscribe();
CodePudding user response:
You could split()
both string on spaces to get an array of each word.
Then we can use every()
to check if input
exist in search
. This way the 'order' is not important.
Combining this with find()
to search for the matching result in an array:
const options = [ 'africa', 'antarctica', 'asia', 'australia', 'europe', 'north america', 'south america' ];
function findByWord(input) {
let inputSplit = input.split(' ');
return options.filter(o => o.split(' ').every(e => inputSplit.includes(e)));
}
const res = findByWord('america north');
console.log(res)
[
"north america"
]
CodePudding user response:
Simplest solution is just to reverse those words you've been given, and assume all casing is correct:
const matchStr = "I Love PHP";
const searchStr = "PHP Love";
if (matchStr.includes(searchStr.split(" ").reverse().join(" "))) {
console.log("Value matched: " matchStr);
}
To implement into your current code, a little more annoying but you can just add an OR condition to your filter
line:
.filter(e => (e.indexOf(keys.toLowerCase()) > -1) || (e.indexOf(keys.toLowerCase().split(" ").reverse().join(" ")) > -1));
CodePudding user response:
I made something more dynamic, where I split the search string and then loop through them inside an Array.filter()
. It's possible that it's easier to achieve this using a regexp. I also added a requirement that the search should ignore words that are shorter than two words, and also mapped the keywords to be lowercase so they are case insensitive.
const continents = [
'africa',
'antarctica',
'asia',
'australia',
'europe',
'north america',
'south america'
]
const filterContinents = (searchStr, continents) => {
const MIN_KEYWORD_LENGTH = 2;
let keywordsArr = searchStr.split(' ')
.filter((keyword) => keyword.length > MIN_KEYWORD_LENGTH)
.map((keyword) => keyword.toLowerCase());
let hasKeywords = keywordsArr.length > 0;
const filterByKeywords = (_contintent) => {
for (const _keyword of keywordsArr) {
if (!_contintent.includes(_keyword)) {
return false
}
}
return hasKeywords
}
return continents.filter(filterByKeywords);
}
let searchStr = 'eur';
console.log({searchStr}, filterContinents(searchStr, continents));
searchStr = 'eu ro pe';
console.log({searchStr}, filterContinents(searchStr, continents));
searchStr = 'America North';
console.log({searchStr}, filterContinents(searchStr, continents));