预期的用户输入:
Apple : 100
Apple:100
Apple: 100
Apple :100
Apple : 100
Apple :100
Apple: 100
预期结果:
Apple : 100
我在结肠:
之间只需要1个空格
码:
string input = "Apple:100";
if (input.Contains(":"))
{
string firstPart = input.Split(':').First();
string lastPart = input.Split(':').Last();
input = firstPart.Trim() + " : " + lastPart.Trim();
}
上面的代码使用Linq
工作,但有没有更短或更高效的代码与性能?
任何帮助,将不胜感激。
你可以用这个衬垫:
input = string.Join(" : ", input.Split(':').Select(x => x.Trim()));
这比分裂两次更有效。但是,如果您想要更高效的解决方案,可以使用StringBuilder
:
var builder = new StringBuilder(input.Length);
char? previousChar = null;
foreach (var ch in input)
{
// don't add multiple whitespace
if (ch == ' ' && previousChar == ch)
{
continue;
}
// add space before colon
if (ch == ':' && previousChar != ' ')
{
builder.Append(' ');
}
// add space after colon
if (previousChar == ':' && ch != ' ')
{
builder.Append(' ');
}
builder.Append(ch);
previousChar = ch;
}
编辑:正如@Jimi的评论中所提到的,似乎foreach版本比LINQ慢。
你可以尝试这种老式的字符串操作:
int colonPos = input.IndexOf(':');
if (colonPos>-1)
{
string s1 = input.Substring(0,colonPos).Trim();
string s2 = input.Substring(colonPos+1, input.Length-colonPos-1).Trim();
string result = $"{s1} : {s2}";
}
是否更高性能,我不知道,Race Your Horses。
编辑:这个更快更简单(在0.132秒内完成100000次训练集迭代):
string result = input.Replace(" ","").Replace(":", " : ");
既然你问过,这里是类似方法之间的比较:
Selman Genç提出的两种方法和另外两种在一些细节上有所不同的方法。
string.Join("[Separator]", string.Split())
此方法使用分隔符将.Split(char[])
生成的字符串数组合在一起,该字符串为原始字符串的每个子字符串创建一个字符串。使用char数组参数中指定的字符作为分隔符标识符生成子字符串。
StringSplitOptions.RemoveEmptyEntries
参数指示仅返回非空子串。
string output = string.Join(" : ", input.Split(new[] { ":", " " }, StringSplitOptions.RemoveEmptyEntries));
StringBuilder.Append(SubString(IndexOf([Separator])))
(非优化:这里使用TrimStart()
和TrimEnd()
)
StringBuilder sb = new StringBuilder();
const string Separator = " : ";
int SplitPosition = input.IndexOf(':');
sb.Append(input.Substring(0, SplitPosition).TrimEnd());
sb.Append(Separator);
sb.Append(input.Substring(SplitPosition + 1).TrimStart());
以下是5种不同条件下的测试结果:
(我提醒自己总是测试.exe
而不是IDE
)
调试模式32位 - Visual Studio IDE 调试模式64位 - Visual Studio IDE 发布模式64位 - Visual Studio IDE 调试模式64位 - 可执行文件 发布模式64位 - 可执行文件
Test Machine: I5 4690K on Asus Z-97K MB
Visual Studio 15.8.2
C# 7.3
==========================================
1 Million iterations x 10 times
Code Optimization: On
==========================================
-------------------------------------------
Debug 32Bit
-------------------------------------------
Selman Genç Join(.Split().Select()): 244 ~ 247 ms
Selman Genç StringBuilder: 299 ~ 303 ms
Counter Test Join(.Split()): 187 ~ 226 ms
Counter Test StringBuilder: 90 ~ 95 ms
-------------------------------------------
Debug 64Bit
-------------------------------------------
Selman Genç Join(.Split().Select()): 242 ~ 259 ms
Selman Genç StringBuilder: 292 ~ 302 ms
Counter Test Join(.Split()): 183 ~ 227 ms
Counter Test StringBuilder: 89 ~ 93 ms
-------------------------------------------
Release 64Bit
-------------------------------------------
Selman Genç Join(.Split().Select()): 235 ~ 253 ms
Selman Genç StringBuilder: 288 ~ 302 ms
Counter Test Join(.Split()): 176 ~ 224 ms
Counter Test StringBuilder: 86 ~ 94 ms
-------------------------------------------
Debug 64Bit - .exe File
-------------------------------------------
Selman Genç Join(.Split().Select()): 232 ~ 234 ms
Selman Genç StringBuilder: 45 ~ 47 ms
Counter Test Join(.Split()): 197 ~ 217 ms
Counter Test StringBuilder: 77 ~ 78 ms
-------------------------------------------
Release 64Bit - .exe File
-------------------------------------------
Selman Genç Join(.Split().Select()): 226 ~ 228 ms
Selman Genç StringBuilder: 45 ~ 48 ms
Counter Test Join(.Split()): 190 ~ 208 ms
Counter Test StringBuilder: 73 ~ 77 ms
样品测试:
string input = "Apple : 100";
Stopwatch sw = new Stopwatch();
sw.Start();
// Counter test StringBuilder
StringBuilder sb1 = new StringBuilder();
const string Separator = " : ";
for (int i = 0; i < 1000000; i++)
{
int SplitPosition = input.IndexOf(':');
sb1.Append(input.Substring(0, SplitPosition).TrimEnd());
sb1.Append(Separator);
sb1.Append(input.Substring(SplitPosition + 1).TrimStart());
sb1.Clear();
}
sw.Stop();
//File write
sw.Reset();
sw.Start();
// Selman Genç StringBuilder
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < 1000000; i++)
{
char? previousChar = null;
foreach (var ch in input)
{
if (ch == ' ' && previousChar == ch) { continue; }
if (ch == ':' && previousChar != ' ') { sb2.Append(' '); }
if (previousChar == ':' && ch != ' ') { sb2.Append(' '); }
sb2.Append(ch);
previousChar = ch;
}
sb2.Clear();
}
sw.Stop();
//File write
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
string output = string.Join(" : ", input.Split(':').Select(x => x.Trim()));
}
sw.Stop();
/*(...)
*/
你表示第一个单词没有任何空格。因此在我看来,最有效的非正则表达式解决方案是从字符串中删除所有空格(因为你不想要任何空格),然后用:
替换:
string input = "Apple : 100";
input = new string(input.ToCharArray()
.Where(c => !Char.IsWhiteSpace(c))
.ToArray());
input = input.Replace(":", " : ");
小提琴here
你可以使用正则表达式:
string input = "Apple: 100";
// Matches zero or more whitespace characters (\s*) followed by
// a colon and zero or more whitespace characters
string result = Regex.Replace(input, @"\s*:\s*", " : "); // Result: "Apple : 100"
我不确定字符串构建器和缩短到数组会有多少性能,但你可以尝试这样的东西。
string input = "Apple:100";
if (input.Contains(":"))
{
string[] parts = input.Split(':');
StringBuilder builder = new StringBuilder();
builder.Append(parts[0].Trim());
builder.Append(" : ");
builder.Append(parts[1].Trim());
input = builder.ToString();
}