这是初始代码的可运行版本(我稍微修改了输入字符串):
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
此正则表达式从输入字符串中找到两个匹配项:
两个匹配项都只包含一个字母 ( \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;
}
看起来我们现在得到了正确的结果!
不过,还有三件事:
- 我们可以修改和链接方法调用,而不是创建和改变
str
变量。this
txt
将变量重命名为变量可能是有意义的match
,因为它们是正则表达式匹配。
- 修改内置对象的原型是个坏主意。创建一个新函数是一个更好的主意。
这是最终的代码:
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)