Tengo el siguiente código en Angular. Quiero poder encontrar "américa del norte" escribiendo "américa del norte". ¿Cómo puedo hacer eso?
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();Puede split() ambas cadenas en espacios para obtener una matriz de cada palabra.
Luego podemos usar every() para verificar si input existe en search . De esta manera el 'orden' no es importante.
Combinando esto con find() para buscar el resultado coincidente en una matriz:
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" ]La solución más simple es simplemente invertir las palabras que le han dado y asumir que todas las mayúsculas y minúsculas son correctas:
const matchStr = "I Love PHP"; const searchStr = "PHP Love"; if (matchStr.includes(searchStr.split(" ").reverse().join(" "))) { console.log("Value matched: " + matchStr); } Para implementar en su código actual, es un poco más molesto, pero puede agregar una condición OR a su línea de filter :
.filter(e => (e.indexOf(keys.toLowerCase()) > -1) || (e.indexOf(keys.toLowerCase().split(" ").reverse().join(" ")) > -1));Hice algo más dinámico, donde dividí la cadena de búsqueda y luego la recorrí dentro de un Array.filter() . Es posible que sea más fácil lograr esto usando una expresión regular. También agregué el requisito de que la búsqueda debe ignorar las palabras que tienen menos de dos caracteres, y también asigné las palabras clave en minúsculas para que no distingan entre mayúsculas y minúsculas.
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));