Since you asked, here's a comparison between similar methods:
The two methods that Selman Genç presented and two other that differ in some details.
string.Join("[Separator]", string.Split())
This method glues together, using a Separator, the array of strings generated by .Split(char[]), which creates a string for each substring of the original one. The substrings are generated using the characters specified in the char array parameter as separator identifiers.
The StringSplitOptions.RemoveEmptyEntries parameter indicates to only return non-empty substrings.
string output = string.Join(" : ", input.Split(new[] { ":", " " }, StringSplitOptions.RemoveEmptyEntries));
StringBuilder.Append(SubString(IndexOf([Separator])))
(non optimized: TrimStart() and TrimEnd() are used here)
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());
Here are the result of the test in 5 different conditions:
(Where I remind myself to always test the .exe and not the IDE)
Debug Mode 32Bit - Visual Studio IDE
Debug Mode 64Bit - Visual
Studio IDE
Release Mode 64Bit - Visual Studio IDE
Debug Mode 64Bit - Executable File
Release Mode 64Bit - Executable File
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
Sample test:
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();
/*(...)
*/