给定字符串“ThisStringHasNoSpacesButItDoesHaveCapitals”,什么是在大写字母之前添加空格的最好方法。所以结尾字符串是"This string Has No space But It Does Have大写"
下面是我使用正则表达式的尝试
System.Text.RegularExpressions.Regex.Replace(value, "[A-Z]", " $0")
给定字符串“ThisStringHasNoSpacesButItDoesHaveCapitals”,什么是在大写字母之前添加空格的最好方法。所以结尾字符串是"This string Has No space But It Does Have大写"
下面是我使用正则表达式的尝试
System.Text.RegularExpressions.Regex.Replace(value, "[A-Z]", " $0")
当前回答
这对聚合来说是个好机会。它被设计成可读的,但不一定特别快。
someString
.Aggregate(
new StringBuilder(),
(str, ch) => {
if (char.IsUpper(ch) && str.Length > 0)
str.Append(" ");
str.Append(ch);
return str;
}
).ToString();
其他回答
正则表达式可以很好地工作(我甚至投票赞成Martin brown的答案),但是它们很昂贵(而且我个人认为任何超过两个字符的模式都非常迟钝)
这个函数
string AddSpacesToSentence(string text, bool preserveAcronyms)
{
if (string.IsNullOrWhiteSpace(text))
return string.Empty;
StringBuilder newText = new StringBuilder(text.Length * 2);
newText.Append(text[0]);
for (int i = 1; i < text.Length; i++)
{
if (char.IsUpper(text[i]))
if ((text[i - 1] != ' ' && !char.IsUpper(text[i - 1])) ||
(preserveAcronyms && char.IsUpper(text[i - 1]) &&
i < text.Length - 1 && !char.IsUpper(text[i + 1])))
newText.Append(' ');
newText.Append(text[i]);
}
return newText.ToString();
}
将在2,968,750个tick中执行100,000次,正则表达式将花费25,000,000个tick(这是编译的正则表达式)。
这是更好的,对于一个给定的更好的值(即更快),但它需要维护更多的代码。“更好”通常是相互竞争的需求的妥协。
更新 这是一个很长的时间,因为我看到这个,我才意识到时间没有更新,因为代码改变了(它只改变了一点)。
在'Abbbbbbbbb'重复100次(即1000字节)的字符串上,100,000次转换的运行需要手工编码函数4,517,177个节拍,下面的Regex需要59,435,719个节拍,使得手工编码函数的运行时间为Regex的7.6%。
更新2 它会考虑首字母缩略词吗?现在会了! if语句的逻辑是相当模糊的,正如你可以看到将它扩展为这样…
if (char.IsUpper(text[i]))
if (char.IsUpper(text[i - 1]))
if (preserveAcronyms && i < text.Length - 1 && !char.IsUpper(text[i + 1]))
newText.Append(' ');
else ;
else if (text[i - 1] != ' ')
newText.Append(' ');
... 一点用都没有!
这里是原始的简单方法,不担心缩略语
string AddSpacesToSentence(string text)
{
if (string.IsNullOrWhiteSpace(text))
return "";
StringBuilder newText = new StringBuilder(text.Length * 2);
newText.Append(text[0]);
for (int i = 1; i < text.Length; i++)
{
if (char.IsUpper(text[i]) && text[i - 1] != ' ')
newText.Append(' ');
newText.Append(text[i]);
}
return newText.ToString();
}
以下是我的解决方案,基于Binary Worriers的建议和Richard Priddys的评论,但也考虑到空白可能存在于提供的字符串中,所以它不会在现有空白旁边添加空白。
public string AddSpacesBeforeUpperCase(string nonSpacedString)
{
if (string.IsNullOrEmpty(nonSpacedString))
return string.Empty;
StringBuilder newText = new StringBuilder(nonSpacedString.Length * 2);
newText.Append(nonSpacedString[0]);
for (int i = 1; i < nonSpacedString.Length; i++)
{
char currentChar = nonSpacedString[i];
// If it is whitespace, we do not need to add another next to it
if(char.IsWhiteSpace(currentChar))
{
continue;
}
char previousChar = nonSpacedString[i - 1];
char nextChar = i < nonSpacedString.Length - 1 ? nonSpacedString[i + 1] : nonSpacedString[i];
if (char.IsUpper(currentChar) && !char.IsWhiteSpace(nextChar)
&& !(char.IsUpper(previousChar) && char.IsUpper(nextChar)))
{
newText.Append(' ');
}
else if (i < nonSpacedString.Length)
{
if (char.IsUpper(currentChar) && !char.IsWhiteSpace(nextChar) && !char.IsUpper(nextChar))
{
newText.Append(' ');
}
}
newText.Append(currentChar);
}
return newText.ToString();
}
这个正则表达式在每个大写字母前放置一个空格字符:
using System.Text.RegularExpressions;
const string myStringWithoutSpaces = "ThisIsAStringWithoutSpaces";
var myStringWithSpaces = Regex.Replace(myStringWithoutSpaces, "([A-Z])([a-z]*)", " $1$2");
注意前面的空间,如果“$1$2”,这是可以完成的。
结果如下:
"This Is A String Without Spaces"
我想用这个
string InsertSpace(string text ) {
return string.Join("" , text.Select(ch => char.IsUpper(ch) ? " " : "" + ch)) ;
}
你的解决方案有一个问题,它在第一个字母T之前放了一个空格,所以你得到
" This String..." instead of "This String..."
要绕开这个问题,请寻找前面的小写字母,然后在中间插入空格:
newValue = Regex.Replace(value, "([a-z])([A-Z])", "$1 $2");
编辑1:
如果你使用@"(\p{Ll})(\p{Lu})",它也会拾取重音字符。
编辑2:
如果你的字符串可以包含首字母缩略词,你可能想使用这个:
newValue = Regex.Replace(value, @"((?<=\p{Ll})\p{Lu})|((?!\A)\p{Lu}(?>\p{Ll}))", " $0");
所以driveisscsiccompatible变成了DriveIsSCSICompatible