Veronica
Veronica

Reputation: 45

RegExp "i" case insensitive VS toLowerCase() (javascript)

I'm hoping someone can explain to me why I need to use "toLowerCase()" if I'm already using a regular expression that is case insensitive "i". The exercise is a pangram that can accept numbers and non-ascii characters, but all letters of the alphabet MUST be present in lower case, upper case, or mixed. I wasn't able to solve this exercise correctly until I added "toLowerCase()". This is one of the javascript exercises from exercism.io. Below is my code:

var Pangram = function (sentence) {
  this.sentence = sentence;
};

Pangram.prototype.isPangram = function (){
  var alphabet = "abcdefghijklmnopqrstuvwxyz", mustHave = /^[a-z]+$/gi, 
  x = this.sentence.toLowerCase(), isItValid = mustHave.test(x);

  for (var i = 0; i < alphabet.length; i++){
    if (x.indexOf(alphabet[i]) === -1 && isItValid === false){
      return false;
    }

  }
  return true;

};

module.exports = Pangram;

Upvotes: 2

Views: 939

Answers (2)

Damon
Damon

Reputation: 4346

The regex may not be doing what you think it's doing. Here is your code commented with what's going on:

Pangram.prototype.isPangram = function (){
  var alphabet = "abcdefghijklmnopqrstuvwxyz", mustHave = /^[a-z]+$/gi, 
  x = this.sentence.toLowerCase(), isItValid = mustHave.test(x);

  // for every letter in the alphabet
  for (var i = 0; i < alphabet.length; i++){
    // check the following conditions:
    // letter exists in the sentence (case sensitive)
    // AND sentence contains at least one letter between a-z (start to finish, case insensitive)
    if (x.indexOf(alphabet[i]) === -1 && isItValid === false){
      return false;
    }

  }
  return true;

}

The logic that is checking whether each letter is present has nothing to do with the regex, the two are serving separate purposes. In fact, based on your description of the problem, the regex will cause your solution to fail in some cases. For example, assume we have the string "abcdefghijklmnopqrstuvwxyz-". In that case your regex will test false even though this sentence should return true.

My advice would be to remove the regex, use toLowerCase on the sentence, and iterate through the alphabet checking if the sentence has each letter - which you seems to be the track you were on.

Below is a sample solution with some tests. Happy learning!

function isPangram (str) {
  const alphabet = 'abcdefghijklmnopqrstuvwxyz'
  const strChars = new Set(str.toLowerCase().split(''))

  return alphabet.split('').every(char => strChars.has(char))
}

const tests = [
  "abc",
  "abcdefghijklmnopqrstuvwxyz",
  "abcdefghijklmnopqRstuvwxyz",
  "abcdefghijklmnopqRstuvwxyz-",
]

tests.forEach(test => {
  console.log(test, isPangram(test))
})

Upvotes: 2

Andy Ray
Andy Ray

Reputation: 32076

It's because you're manually checking for lowercase letters:

if (x.indexOf(alphabet[i]) === -1)

alphabet[i] will be one of your alphabet string, which you have defined as lowercase.

It looks like you don't need the regex at all here, or at least it's not doing what you think it's doing. Since your regex only allows for alpha characters, it will fail if your sentence has any spaces.

Upvotes: 1

Related Questions