RegExp "i" 不区分大小写 VS toLowerCase() (javascript)

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

如果我已经在使用不区分大小写的正则表达式 "i",我希望有人能向我解释为什么我需要使用 "toLowerCase()"。 练习是一个可以接受数字和非 ascii 字符的 pangram,但字母表中的所有字母必须以小写、大写或混合形式出现。在添加 "toLowerCase()" 之前,我无法正确解决此练习。这是 exercism.io 中的 javascript 练习之一。下面是我的代码:

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;

这是因为您正在手动检查小写字母:

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

alphabet[i] 将是您定义为小写的字母字符串之一。

看起来你在这里根本不需要正则表达式,或者至少它没有按照你认为的那样做。由于您的正则表达式只允许字母字符,因此如果您的句子有任何空格,它将失败。

正则表达式可能与您认为的不一样。这是你的代码评论了发生了什么:

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;

}

检查每个字母是否存在的逻辑与正则表达式无关,两者有不同的用途。事实上,根据您对问题的描述,正则表达式在某些情况下会导致您的解决方案失败。例如,假设我们有字符串 "abcdefghijklmnopqrstuvwxyz-"。在那种情况下,即使这句话应该 return 为真,你的正则表达式也会测试为假。

我的建议是删除正则表达式,在句子上使用 toLowerCase,然后遍历字母表检查句子中是否有每个字母 - 你似乎就是你所在的轨道。

下面是一个带有一些测试的示例解决方案。学习愉快!

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