在字符串中的冒号之间添加空格

时间:2018-08-29 13:44:59

标签: c# .net

预期的用户输入:

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进行工作,但是是否有较短或更有效的代码同时考虑了性能?

任何帮助将不胜感激。

6 个答案:

答案 0 :(得分:9)

您可以使用这种衬板:

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慢。

答案 1 :(得分:5)

您可以尝试这种老式的字符串操作:

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(":", " : ");

答案 2 :(得分:3)

根据您的要求,以下是类似方法之间的比较:

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
释放模式64Bit-Visual Studio IDE
调试模式64Bit-可执行文件
释放模式64Bit-可执行文件

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();

/*(...)
*/

答案 3 :(得分:1)

您表示第一个单词不能有空格。因此,我认为最有效的非正则表达式解决方案是从字符串中删除所有空格(因为您不需要),然后将:替换为:

string input = "Apple   :     100";
input = new string(input.ToCharArray()
                 .Where(c => !Char.IsWhiteSpace(c))
                 .ToArray());
input = input.Replace(":", " : ");

提琴here

答案 4 :(得分:0)

您可以使用正则表达式:

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"

答案 5 :(得分:0)

我不确定字符串构建器和缩短为数组的性能如何,但是您可以尝试这样的操作。

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();
}