Find letters in random string exactly, using RegEx

Viewed 252

The emphasis here is on the word exactly. This needs to work for any number of permutations, so hopefully my example is clear enough.

Given a string of random letters, is it possible (using RegEx) to match an exact number of letters within the given string?

So if I have a string (str1) containing letters ABZBABJDCDAZ and I wanted to match the letters JDBBAA (str2), my function should return true because str1 contains all the right letters enough times. If however str1 were to be changed to ABAJDCDA, then the function would return false as str2 requires that str1 have at least 2 instances of the letter B.

This is what I have so far using a range:

const findLetters = (str1, str2) => {
  const regex = new RegExp(`[${str2}]`, 'g')
  const result = (str1.match(regex))
  console.log(result)
}

findLetters('ABZBABJDCDAZ', 'JDBBAA')

As you can see it matches the right letters, but it matches all instances of them. Is there any way to do what I'm trying to do using RegEx? The reason I'm focusing on RegEx here is because I need this code to be highly optimised, and so far my other functions using Array.every() and indexOf() are just too slow.

Note: My function only requires to return a true/false value.

2 Answers

Try (here we sort letters of both strings and then create regexp like A.*A.*B.*B.*D.*J)

const findLetters = (str1, str2) => {
  const regex = new RegExp([...str2].sort().join`.*`)
  return regex.test([...str1].sort().join``)
}

console.log( findLetters('ABZBABJDCDAZ', 'JDBBAA') );
console.log( findLetters('ABAJDCDA', 'JDBBAA') );

I dont know if regex is the right way for this as this can also get very expensive. Regex is fast, but not always the fastest.

const findLetters2 = (strSearchIn, strSearchFor) => {
  var strSearchInSorted = strSearchIn.split('').sort(function(a, b) {
    return a.localeCompare(b);
  });
  var strSearchForSorted = strSearchFor.split('').sort(function(a, b) {
    return a.localeCompare(b);
  });

  return hasAllChars(strSearchInSorted, strSearchForSorted);
}

const hasAllChars = (searchInCharList, searchCharList) => {
  var counter = 0;
  for (i = 0; i < searchCharList.length; i++) {
    var found = false;
    for (counter; counter < searchInCharList.length;) {
      counter++;
      if (searchCharList[i] == searchInCharList[counter - 1]) {
        found = true;
        break;
      }
    }
    if (found == false) return false;
  }
  return true;
}

// No-Regex solution
console.log('true: ' + findLetters2('abcABC', 'abcABC'));
console.log('true: ' + findLetters2('abcABC', 'acbACB'));
console.log('true: ' + findLetters2('abcABCx', 'acbACB'));
console.log('false: ' + findLetters2('abcABC', 'acbACBx'));
console.log('true: ' + findLetters2('ahfffmbbbertwcAtzrBCasdf', 'acbACB'));
console.log('false: ' + findLetters2('abcABC', 'acbAACB'));

Feel free to test it's speed and to optimize it as I'm no js expert. This solution should iterate each string once after sorting. Sorting is thanks to https://stackoverflow.com/a/51169/9338645.

Related