C# 连接速度更快的方法

5

我在我的代码上运行了Visual Studio分析,发现大量时间都花费在字符串拼接上。有没有更快的方法可以进行字符串拼接?

    string[] infoseperated = info.Split(' ');   
    for (int iii = totalremove; iii < infoseperated.Length; iii++)
    {
    newinfo += infoseperated[iii] + " ";
    }

1
在那个具体的循环中还是一般情况下? - Joachim Isaksson
9个回答

13

使用 string.Join 替代:

newinfo = string.Join(" ", infoseperated.Skip(totalremove));

你当前的方法对每个字符串连接都生成一个新的字符串(因为字符串是不可变的,所以必须重新分配一个新的字符串),这很昂贵。

对于每个连接,现有字符串的所有字符都必须复制到新字符串中,因此此操作的成本随着字符串中字符数的增加而增加 - 这是Schlemiel the Painter's algorithm

string.Join 在内部使用StringBuilder来避免这种情况。


你需要使用 infoseparated.Skip(totalremove) 来匹配原帖的语义。 - jason
@BrokenGlass Skip将不得不对数组进行类型检查,以查看它是否实现了IList<string>; 带有起始索引和长度参数的Join重载可能更有效率。 - phoog
@phoog:也许,如果你需要挤出这个程序的最后一点性能。Skip版本更易读,所以这也是一个因素。 - jason
有没有办法在使用join时也设置最大限制?可以使用一个名为total的变量来代替infoseperated.Length作为最大值。 - user1158903
@caseyr547:在上面的例子中,你可以添加 Take(count)infoseperated.Skip(totalremove).Take(count) - BrokenGlass
显示剩余2条评论

4

1
StringBuilder 对于一般情况是不错的选择,但对于这种特定情况,String.Join 可能更合适。 - Yaur

1
每次使用 + 运算符连接字符串时,都会创建一个新的对象。相反,请使用 StringBuilder 类。

0

尝试使用 StringBuilder

        StringBuilder sb = new StringBuilder();
        int totalremove = 0;
        string[] infoseperated = info.Split(' ');
        for (int iii = totalremove; iii < infoseperated.Length; iii++)
        {
            sb.Append(infoseperated[iii]);
            sb.Append(" ");
        }
        newinfo = sb.ToString();

0

正如其他许多答案所说,直接或间接地使用 StringBuilder(通过 string.Join)将具有更好的性能。但是,在您的示例 Split & Join 中,我认为我们可以做得更好。

// first, find the n-th (totalremove-th) separating space.
int index = 0;
for(int i = 0; i < totalremove; i++)
{
    index = infoseperated.IndexOf(' ', index + 1);
    if(index == -1) return ""; // e.g., asked to remove 5 values, but only 3 in the string.
}

// return everything after that point.
return infoseperated.Substring(index + 1);

只要infoseperated没有双空格,或者开头有空格之类的问题,这种方法比分割和重新组合字符串更有效率。

0
使用 System.Text.StringBuilder。它的性能比字符串拼接要好。

String.Join在这种情况下更好,因为写入的代码更少。 - jason

0

string.Joinstring.Appendstring.Format("") 可能比添加字符串更有效率,然而这并不意味着你一定会提高速度到你真正想要的程度。你应该尝试着看大局,并真正确定为什么你需要如此频繁地连接字符串,如果你可以将这个操作最小化,那么可能比仅仅使用最有效的连接方法好。


1
这是错误的。无论如何,+编译成Concat,而Concat受到Schlemiel the Painter问题的影响。 - jason
我已经取消了我的踩票,因为你根据我的先前评论编辑了你的答案。 - jason
@Jason,谢谢...我的回答的要点是使用最快的连接方法是好的,但如果可能的话,最好完全消除瓶颈。 - Kiril

0

其他答案正确地建议使用string.Join,但他们建议错误的重载:

newInfo = string.Join(" ", infoseparated, totalremove, infoseparated.Length - totalremove);

或者你可以将infoseparated.Skip(totalremove)作为第二个参数传递给String.Join。 - jason
@Jason 是的,但是 Skip 调用会有更多的开销,所以如果性能很关键,Join(string, string[], int, int) 调用可能更好。 - phoog

0
如果性能是最大的关注点,最快的方法可能是根本不拆分字符串,并且除了获取子字符串之外不会产生任何内存分配开销。
string newinfo;
while (totalremove-- > 0 && (index = info.IndexOf(' ', index)) >= 0) index+=1;
if (index >= 0)
    newinfo = info.Substring(index);
else
    newinfo = "";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接