1

我正在研究将一串文本转换为同样保留首字母缩略词的句子大小写的代码。我确实在 StackOverflow 中探索过类似的帖子,但是,我找不到适合我要求的帖子。

我已经实现了Acronyms和句子中首字母的转换。但是,我遇到了其他问题,例如句子中的某些字母仍然是大写的,尤其是双引号(“”)和驼峰文本中和之后的文本。

以下是我目前正在处理的代码,我需要有人帮助我优化代码并解决问题。

String.prototype.toSentenceCase = function() {
  var i, j, str, lowers, uppers;
  str = this.replace(/(^\w{1}|\.\s*\w{1})/gi, function(txt) {
    return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
  });

  
  // Certain words such as initialisms or acronyms should be left uppercase
  uppers = ['Id', 'Tv', 'Nasa', 'Acronyms'];
  for (i = 0, j = uppers.length; i < j; i++)
    str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'),
      uppers[i].toUpperCase());

 // To remove Special caharacters like ':' and '?'
    str = str.replace(/[""]/g,'');
    str = str.replace(/[?]/g,'');
    str = str.replace(/[:]/g,' - ');

return str;
}

输入:play around:这是一个“字符串”文本,需要转换为句子大小写,同时保持首字母缩写词与 Nasa 一样。

当前输出:播放 - 这是一个文本字符串,需要将其转换为句子大小写,同时保持缩写词与 NASA 一样。

预期输出:播放 - 这是一串文本,需要将其转换为句子大小写,同时保持 ACRONYMS 就像 NASA 一样。

4

1 回答 1

1

这是初始代码的可运行版本(我稍微修改了输入字符串):

String.prototype.toSentenceCase = function() {
  var i, j, str, lowers, uppers;
  str = this.replace(/(^\w{1}|\.\s*\w{1})/gi, function(txt) {
    return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
  });

  
  // Certain words such as initialisms or acronyms should be left uppercase
  uppers = ['Id', 'Tv', 'Nasa', 'Acronyms'];
  for (i = 0, j = uppers.length; i < j; i++)
    str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'),
      uppers[i].toUpperCase());

 // To remove Special caharacters like ':' and '?'
    str = str.replace(/[""]/g,'');
    str = str.replace(/[?]/g,'');
    str = str.replace(/[:]/g,' - ');

return str;
}

const input = `play around: This is a "String" Of text, which needs to be cONVERTED to Sentence Case at the same time keeping the Acronyms as it is like Nasa. another sentence. "third" sentence starting with a quote.`
const result = input.toSentenceCase()
console.log(result)


我遇到了其他问题,例如句子中的某些字母仍然大写,尤其是双引号(“”)和驼峰式文本中和之后的文本。

有些字母保持大写,因为您没有.toLowerCase()在代码中的任何地方调用。期望在一开始,但该正则表达式仅针对句子的首字母,而不是其他字母。

首先将所有字母小写,然后将一些字母(首字母缩写词和句子的首字母)大写会很有帮助。所以,让我们.toLowerCase()在开始时调用:

String.prototype.toSentenceCase = function() {
  var i, j, str, lowers, uppers;

  str = this.toLowerCase();

  // ...

  return str;
}

接下来,让我们看一下这个正则表达式:

/(^\w{1}|\.\s*\w{1})/gi

括号是不必要的,因为在替换函数中没有使用捕获组。{1}量词也是不必要的,因为默认情况下只\w匹配一个字符。所以我们可以像这样简化正则表达式:

/^\w|\.\s*\w/gi

此正则表达式从输入字符串中找到两个匹配项:

  • p
  • . a

两个匹配项都只包含一个字母 ( \w),因此在替换函数中,我们可以安全地调用txt.toUpperCase()而不是当前更复杂的表达式 ( txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase())。我们还可以使用箭头函数:

String.prototype.toSentenceCase = function() {
  var i, j, str, lowers, uppers;

  str = this.toLowerCase();

  str = str.replace(/^\w|\.\s*\w/gi, (txt) => txt.toUpperCase());

  // ...

  return str;
}

但是,第三个句子的首字母不是大写的,因为该句子以引号开头。因为无论如何我们都要删除引号和问号,所以让我们从一开始就这样做。

让我们也简化和组合正则表达式:

// Before
str = str.replace(/[""]/g,'');
str = str.replace(/[?]/g,'');
str = str.replace(/[:]/g,' - ');

// After
str = str.replace(/["?]/g,'');
str = str.replace(/:/g,' - ');

所以:

String.prototype.toSentenceCase = function() {
  var i, j, str, lowers, uppers;

  str = this;

  str = str.toLowerCase();

  str = str.replace(/["?]/g,'');
  str = str.replace(/:/g,' - ');

  str = str.replace(/^\w|\.\s*\w/gi, (txt) => txt.toUpperCase());

  // ...

  return str;
}

现在第三句的首字母正确大写。那是因为当我们将首字母大写时,第三句不再以引号开头(因为我们已经删除了引号)。

剩下的是大写首字母缩写词。在您的正则表达式中,您可能还希望将该i标志用于不区分大小写的匹配。

for可以使用单个正则表达式来查找所有匹配项并将它们大写,而不是使用循环。这也使我们能够摆脱大部分变量。像这样:

String.prototype.toSentenceCase = function() {
  var str;

  str = this;

  str = str.toLowerCase();

  str = str.replace(/["?]/g,'');
  str = str.replace(/:/g,' - ');

  str = str.replace(/^\w|\.\s*\w/gi, (txt) => txt.toUpperCase());

  str = str.replace(/\b(id|tv|nasa|acronyms)\b/gi, (txt) => txt.toUpperCase());

  return str;
}

看起来我们现在得到了正确的结果!

不过,还有三件事:

  1. 我们可以修改和链接方法调用,而不是创建和改变str变量。this
  2. txt将变量重命名为变量可能是有意义的match,因为它们是正则表达式匹配。
  3. 修改内置对象的原型是个坏主意。创建一个新函数是一个更好的主意。

这是最终的代码:

function convertToSentenceCase(str) {
  return str
    .toLowerCase()
    .replace(/["?]/g, '')
    .replace(/:/g, ' - ')
    .replace(/^\w|\.\s*\w/gi, (match) => match.toUpperCase())
    .replace(/\b(id|tv|nasa|acronyms)\b/gi, (match) => match.toUpperCase())
}

const input = `play around: This is a "String" Of text, which needs to be cONVERTED to Sentence Case at the same time keeping the Acronyms as it is like Nasa. another sentence. "third" sentence starting with a quote.`
const result = convertToSentenceCase(input)
console.log(result)

于 2021-01-21T09:48:02.200 回答