给定字符串“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")
当前回答
我想用这个
string InsertSpace(string text ) {
return string.Join("" , text.Select(ch => char.IsUpper(ch) ? " " : "" + ch)) ;
}
其他回答
这个问题有点老了,但现在在Nuget上有一个很好的库,它可以做到这一点,以及许多其他转换到人类可读的文本。
在GitHub或Nuget上检查Humanizer。
例子
"PascalCaseInputStringIsTurnedIntoSentence".Humanize() => "Pascal case input string is turned into sentence"
"Underscored_input_string_is_turned_into_sentence".Humanize() => "Underscored input string is turned into sentence"
"Underscored_input_String_is_turned_INTO_sentence".Humanize() => "Underscored input String is turned INTO sentence"
// acronyms are left intact
"HTML".Humanize() => "HTML"
对于任何正在寻找回答这个问题的c++函数的人,您可以使用下面的方法。这是模仿@Binary Worrier给出的答案。这种方法只是自动保留首字母缩略词。
using namespace std;
void AddSpacesToSentence(string& testString)
stringstream ss;
ss << testString.at(0);
for (auto it = testString.begin() + 1; it != testString.end(); ++it )
{
int index = it - testString.begin();
char c = (*it);
if (isupper(c))
{
char prev = testString.at(index - 1);
if (isupper(prev))
{
if (index < testString.length() - 1)
{
char next = testString.at(index + 1);
if (!isupper(next) && next != ' ')
{
ss << ' ';
}
}
}
else if (islower(prev))
{
ss << ' ';
}
}
ss << c;
}
cout << ss.str() << endl;
我为这个函数使用的测试字符串,结果是:
"helloWorld" -> "helloWorld" "HelloWorld" -> "HelloWorld" "HelloABCWorld" -> "HelloABCWorld" "HelloWorldABC" -> "HelloWorldABC" "ABCHelloWorld" -> "ABCHelloWorld" " abc hello world " -> " abc hello world " " abchelloworld " -> " abchelloworld " " a " -> " a "
欢迎来到Unicode
所有这些解决方案对于现代文本来说本质上都是错误的。你需要使用能理解大小写的东西。由于Bob要求使用其他语言,我将为Perl提供两种语言。
我提供了四种解决方案,从最坏到最好。只有最好的人才是对的。其他人都有问题。下面是一个测试运行,向您展示什么可行,什么不可行,以及在哪里。我用了下划线,这样你们就能看到空格放在了哪里,我把所有错的地方都标记了出来。
Testing TheLoneRanger
Worst: The_Lone_Ranger
Ok: The_Lone_Ranger
Better: The_Lone_Ranger
Best: The_Lone_Ranger
Testing MountMᶜKinleyNationalPark
[WRONG] Worst: Mount_MᶜKinley_National_Park
[WRONG] Ok: Mount_MᶜKinley_National_Park
[WRONG] Better: Mount_MᶜKinley_National_Park
Best: Mount_Mᶜ_Kinley_National_Park
Testing ElÁlamoTejano
[WRONG] Worst: ElÁlamo_Tejano
Ok: El_Álamo_Tejano
Better: El_Álamo_Tejano
Best: El_Álamo_Tejano
Testing TheÆvarArnfjörðBjarmason
[WRONG] Worst: TheÆvar_ArnfjörðBjarmason
Ok: The_Ævar_Arnfjörð_Bjarmason
Better: The_Ævar_Arnfjörð_Bjarmason
Best: The_Ævar_Arnfjörð_Bjarmason
Testing IlCaffèMacchiato
[WRONG] Worst: Il_CaffèMacchiato
Ok: Il_Caffè_Macchiato
Better: Il_Caffè_Macchiato
Best: Il_Caffè_Macchiato
Testing MisterDženanLjubović
[WRONG] Worst: MisterDženanLjubović
[WRONG] Ok: MisterDženanLjubović
Better: Mister_Dženan_Ljubović
Best: Mister_Dženan_Ljubović
Testing OleKingHenryⅧ
[WRONG] Worst: Ole_King_HenryⅧ
[WRONG] Ok: Ole_King_HenryⅧ
[WRONG] Better: Ole_King_HenryⅧ
Best: Ole_King_Henry_Ⅷ
Testing CarlosⅤºElEmperador
[WRONG] Worst: CarlosⅤºEl_Emperador
[WRONG] Ok: CarlosⅤº_El_Emperador
[WRONG] Better: CarlosⅤº_El_Emperador
Best: Carlos_Ⅴº_El_Emperador
顺便说一下,这里几乎所有人都选择了第一种方式,即标记为“最差”的方式。少数人选择了标记为“OK”的第二种方式。但是在我之前没有人告诉过你如何做“更好”或“最好”的方法。
下面是带有四个方法的测试程序:
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
# First I'll prove these are fine variable names:
my (
$TheLoneRanger ,
$MountMᶜKinleyNationalPark ,
$ElÁlamoTejano ,
$TheÆvarArnfjörðBjarmason ,
$IlCaffèMacchiato ,
$MisterDženanLjubović ,
$OleKingHenryⅧ ,
$CarlosⅤºElEmperador ,
);
# Now I'll load up some string with those values in them:
my @strings = qw{
TheLoneRanger
MountMᶜKinleyNationalPark
ElÁlamoTejano
TheÆvarArnfjörðBjarmason
IlCaffèMacchiato
MisterDženanLjubović
OleKingHenryⅧ
CarlosⅤºElEmperador
};
my($new, $best, $ok);
my $mask = " %10s %-8s %s\n";
for my $old (@strings) {
print "Testing $old\n";
($best = $old) =~ s/(?<=\p{Lowercase})(?=[\p{Uppercase}\p{Lt}])/_/g;
($new = $old) =~ s/(?<=[a-z])(?=[A-Z])/_/g;
$ok = ($new ne $best) && "[WRONG]";
printf $mask, $ok, "Worst:", $new;
($new = $old) =~ s/(?<=\p{Ll})(?=\p{Lu})/_/g;
$ok = ($new ne $best) && "[WRONG]";
printf $mask, $ok, "Ok:", $new;
($new = $old) =~ s/(?<=\p{Ll})(?=[\p{Lu}\p{Lt}])/_/g;
$ok = ($new ne $best) && "[WRONG]";
printf $mask, $ok, "Better:", $new;
($new = $old) =~ s/(?<=\p{Lowercase})(?=[\p{Uppercase}\p{Lt}])/_/g;
$ok = ($new ne $best) && "[WRONG]";
printf $mask, $ok, "Best:", $new;
}
当你能在这个数据集上得到与“最佳”相同的分数时,你就知道你做对了。在那之前,你还没有。这里没有人比“还行”做得更好,大多数人都做得“最差”。我期待看到有人发布正确的ℂ代码。
我注意到,StackOverflow的高亮代码是悲惨的笨拙再次。他们所做的一切都和这里提到的其他糟糕的方法一样(大部分但不是全部)。难道不是早就该让ASCII停止使用了吗?这已经没有意义了,假装这是你的全部是大错特错的。这会导致糟糕的代码。
在小写字母、大写字母或数字后添加空格的简单方法。
string AddSpacesToSentence(string value, bool spaceLowerChar = true, bool spaceDigitChar = true, bool spaceSymbolChar = false)
{
var result = "";
for (int i = 0; i < value.Length; i++)
{
char currentChar = value[i];
char nextChar = value[i < value.Length - 1 ? i + 1 : value.Length - 1];
if (spaceLowerChar && char.IsLower(currentChar) && !char.IsLower(nextChar))
{
result += value[i] + " ";
}
else if (spaceDigitChar && char.IsDigit(currentChar) && !char.IsDigit(nextChar))
{
result += value[i] + " ";
}
else if(spaceSymbolChar && char.IsSymbol(currentChar) && !char.IsSymbol(nextChar))
{
result += value[i];
}
else
{
result += value[i];
}
}
return result;
}
我把Kevin Strikers优秀的解决方案转换为VB。由于我被锁定在。net 3.5,我还必须写IsNullOrWhiteSpace。这通过了他所有的测试
<Extension()>
Public Function IsNullOrWhiteSpace(value As String) As Boolean
If value Is Nothing Then
Return True
End If
For i As Integer = 0 To value.Length - 1
If Not Char.IsWhiteSpace(value(i)) Then
Return False
End If
Next
Return True
End Function
<Extension()>
Public Function UnPascalCase(text As String) As String
If text.IsNullOrWhiteSpace Then
Return String.Empty
End If
Dim newText = New StringBuilder()
newText.Append(text(0))
For i As Integer = 1 To text.Length - 1
Dim currentUpper = Char.IsUpper(text(i))
Dim prevUpper = Char.IsUpper(text(i - 1))
Dim nextUpper = If(text.Length > i + 1, Char.IsUpper(text(i + 1)) Or Char.IsWhiteSpace(text(i + 1)), prevUpper)
Dim spaceExists = Char.IsWhiteSpace(text(i - 1))
If (currentUpper And Not spaceExists And (Not nextUpper Or Not prevUpper)) Then
newText.Append(" ")
End If
newText.Append(text(i))
Next
Return newText.ToString()
End Function