使用正则表达式检查字符串错误中的 pangram

Using regular expression to check for pangram in a string error

Roy wanted to increase his typing speed for programming contests. His friend suggested that he type the sentence "The quick brown fox jumps over the lazy dog" repeatedly. This sentence is known as a pangram because it contains every letter of the alphabet.

After typing the sentence several times, Roy became bored with it so he started to look for other pangrams.

Given a sentence, determine whether it is a pangram. Ignore case.

It should return the string pangram if the input string is a pangram. Otherwise, it should return not pangram.

样本输入

我们及时判断了下一个奖品的古董象牙带扣

// 全拼图

我们及时评判了古董象牙带扣的奖品

// 不是 pangram(缺少字母 x)

代码

function pangrams(s) {

   const exp = /[a-z]/gi; 

   if (s.includes(exp)) {
     return 'pangram';
   } else {
     return 'not pangram';
   } 
   
}

TypeError:String.prototype.includes 的第一个参数不能是正则表达式

问题

如果我以其他方式正确解决它,我如何在仍然能够使用正则表达式的同时解决这个问题?

你的正则表达式是错误的。它只会检查字符串是否包含 一个 az 的字母。您也没有正确测试它 - String.prototype.includes 检查 substrings 是否包含在较大的字符串中,而不是用于正则表达式验证。

如果要测试正则表达式是否匹配字符串,请使用.test。要使用正则表达式检查字符串中是否存在所有字母,您必须对每个字符重复 (?=.*a),例如:

const pattern = /^(?=.*a)(?=.*b)(?=.*c)(?=.*d)(?=.*e)...../i;
return s.test(pattern);

但这真的很丑陋且重复。

我认为正则表达式不是解决问题的方法。考虑迭代字符代码以获取从 A 到 Z 的字符并使用 .includes 代替:

const test = (str) => {
  const strUpper = str.toUpperCase();
  // start at A
  for (let i = 65; i <= 90; i++) {
    if (!strUpper.includes(String.fromCharCode(i))) {
      return false;
    }
  }
  return true;
};
console.log(test('The quick brown fox jumps over the lazy dog'));
console.log(test('The quick brown fox jumps over the lazy do'));

如果您使用正则表达式,您可以通过遍历所有字符代码动态构建它:

const test = (str) => {
  const pattern = new RegExp(
    '^' +
    Array.from(
      { length: 26 },
      (_, i) => `(?=.*${String.fromCharCode(i + 65)})`
    ).join(''),
    'i'
  );
  return pattern.test(str);
};
console.log(test('The quick brown fox jumps over the lazy dog'));
console.log(test('The quick brown fox jumps over the lazy do'));

我不会在这里使用正则表达式,因为它可能不是最佳解决方案。相反,考虑将您的输入字符串转换为字母映射,然后断言存在 26 个键:

var letters = {};
var input = "The quick brown fox jumps over the lazy dog";
input = input.replace(/[^A-Za-z]+/g, "");
for (var i=0; i < input.length; i++) {
    letters[input.charAt(i).toLowerCase()] = 1;
}

if (Object.keys(letters).length == 26)
    console.log("PANGRAM");
else
    console.log("NOT A PANGRAM");

这里的方法首先删除所有非字母字符。然后它构建一个映射,其中每个键都是输入中出现的任何字母的小写版本。一个匹配的 pangram 有 26 个键,这意味着它包含字母表中的所有字母。

[a-z] 符号检查任何单个字母字符 - 在您的情况下,您可以首先使用 lowerCase 删除大小写,然后添加字母字符正则表达式以匹配所有唯一字符,然后使a Set出来去掉重复,最后检查长度是否为26:

const pangram = s => {

  const lower = s.toLowerCase();
  const letters = lower.match(/[a-z]/gi);
  const uniques = new Set(letters);
  
  if (uniques.size == 26) return "Pangram";
  else return "Not pangram";

};

console.log(pangram("The quick brown fox jumps over the lazy dog"));
console.log(pangram("Not a pangram lol"));

上面的代码也可以精简:

const pangram = s => new Set(s.toLowerCase().match(/[a-z]/gi)).size == 26 ? "Pangram" : "Not pangram";

console.log(pangram("The quick brown fox jumps over the lazy dog"));
console.log(pangram("Not a pangram lol"));