1

Roy 想提高他在编程比赛中的打字速度。他的朋友建议他反复输入句子“The quick brown fox jumps over the lazy dog”。这句话被称为 pangram,因为它包含字母表的每个字母。

把这句话打了好几遍,罗伊看腻了,于是开始寻找其他的pangram。

给定一个句子,判断它是否是一个 pangram。忽略大小写。

如果输入字符串是 pangram,它应该返回字符串 pangram。否则,它不应该返回 pangram。

样本输入

我们及时为下一个奖项评选出古董象牙扣

// 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 的第一个参数不能是正则表达式

问题

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

4

3 回答 3

2

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

如果要测试正则表达式是否与字符串匹配,请使用.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'));

于 2020-05-11T06:45:35.323 回答
2

[a-z]符号检查任何单个字母字符 - 在您的情况下,您可以首先使用 删除大小写lowerCase,然后添加一个字母字符正则表达式以匹配所有唯一字符,然后使用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"));

于 2020-05-11T06:55:17.973 回答
1

我不会在这里使用正则表达式,因为它可能不是最佳解决方案。相反,请考虑将您的输入字符串转换为字母映射,然后断言存在 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 个键,这意味着它包含字母表中的所有字母。

于 2020-05-11T06:52:51.823 回答