RegExp "i" без учета регистра VS toLowerCase() (JavaScript)
Я надеюсь, что кто-то может объяснить мне, почему мне нужно использовать "toLowerCase()", если я уже использую регулярное выражение, которое не учитывает регистр "i". Упражнение представляет собой панграмму, которая может принимать цифры и символы, отличные от ascii, но все буквы алфавита ДОЛЖНЫ присутствовать в нижнем регистре, верхнем регистре или в смешанном виде. Я не смог правильно выполнить это упражнение, пока не добавил "toLowerCase()". Это одно из упражнений javascript из exercism.io. Ниже мой код:
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;
2 ответа
Это потому, что вы вручную проверяете наличие строчных букв:
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-"
, В этом случае ваше регулярное выражение будет проверять ложь, даже если это предложение должно возвращать истину.
Мой совет будет удалить регулярное выражение, используйте 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))
})