Home > Software engineering >  How do I search a string "backwards"?
How do I search a string "backwards"?

Time:04-30

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));

  • Related