最有效的连接字符串的方式
我需要连接很多字符串并在其中任何一个之间加上逗号。 我有一个字符串列表
"123123123213" "1232113213213" "123213123"
而且我想得到
"123123123213,1232113213213,123213123"
我想知道实现这一目标的最佳方法是什么。
我可以这样做:
private List stringList = new List { // a lot of strings in here "1234567890", "34343434", "4343434" }; string outcome = string.Join(",", stringList.ToArray());
或者可能:
StringBuilder builder = new StringBuilder(); stringList.ForEach(val => { builder.Append(val); builder.Append(","); }); string outcome = builder.ToString();
哪种方式更好? 你知道连接字符串的更好方法吗?
正如@Ekkehard所说,使用string.Join 。
但是,您不需要ToArray()
因为string.Join
具有IEnumerable
的重载。
List stringList = new List { "1234567890", "34343434", "4343434" }; string outcome = string.Join(",", stringList);
编辑
正如@Kobi所说,这只适用于C#4.0。 在3.5我会这样做。
var s = new StringBuilder(stringList.Count * 8); foreach (var item in stringList) { s.Append(item); s.Append(','); } s.Length -= 1; string outcome = stringList.ToList();
你应该使用string.Join()
因为:
a)它的可读性,可维护性和易用性。
b)它内部已经使用了StringBuilder
,所以它非常有效(你可以使用Reflector确认自己)。
编辑:
string.Join()
使用StringBuilder
作为IEnumerable
输入的一般情况。 如果你已经拥有一个数组,那么它使用一些巫术魔法(包括FastAllocateString()
和UnSafeCharBuffer
)甚至更快。
使用Join,因为它不会添加尾随“,”。
这个页面上有一个基准测试,似乎表明在很多迭代中, string.Join
在一个小数组上的性能优于StringBuilder
。 您也应该对较大的arrays进行基准测试。 正如我发布的那样,我看到BrokenGlass回答说StringBuilder
是在string.Join
内部使用的,所以你可以期待它更快。
最后,你的第二个解决方案增加了额外的解决方案 看看Eric Lippert的博客文章
我建议修复你的第二个解决方案。 StringBuilder肯定会更快,因为您避免将列表内容复制到新数组。
StringBuilder builder = new StringBuilder(); string separator = ""; stringList.ForEach( val => { builder.Append(separator).Append(val); separator = ","; }); string outcome = builder.ToString();
StringBuilder是一种非常有效的方法,在这里推荐使用。
根据我做的以下测试, Join在大型arrays上的速度提高了3倍 :
Text.txt
文件包含38400行的值"aaaaaaaaaaaaaaaaaaa"
:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Diagnostics; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var strings = File.ReadAllLines("Text.txt"); Stopwatch sw; StringBuilder sb = new StringBuilder(); sw = Stopwatch.StartNew(); for (int i = 0; i < strings.Length; i++) { sb.AppendLine(strings[i]); } sw.Stop(); TimeSpan sbTime = sw.Elapsed; sw = Stopwatch.StartNew(); var output = string.Join(",", strings); sw.Stop(); TimeSpan joinTime = sw.Elapsed; } } }
输出:
00:00:00.0098754 00:00:00.0032922
如果要加入固定数量的字符串, String.Join是最快的。 更深层次的原因是String.Join循环遍历数组并分配具有正确大小的最终字符串缓冲区,因为它在第一遍中将所有字符串的字符串长度添加到一起。 当您使用StringBuilder及其容量时,您可以获得类似的结果。 黄金法则是以两次循环数组为代价来节省内存分配。 哪种方法更快取决于列表中有多少项以及resultint字符串的大小。
你的,Alois Kraus
测试代码:
public static void Performance(Action fn) { var timer = new Stopwatch(); timer.Start(); for (var i = 0; i < 10000000; ++i) { fn(); } timer.Stop(); Console.WriteLine("{0} Time: {1}ms ({2})", fn.ToString(), timer.ElapsedMilliseconds, timer.ElapsedTicks); } static void Main(string[] args) { var stringList = new List() { "123123123213", "1232113213213", "123213123" }; string outcome = String.Empty; Performance(() => { outcome = string.Join(",", stringList); }); Console.WriteLine(outcome); Performance(() => { StringBuilder builder = new StringBuilder(); stringList.ForEach ( val => { builder.Append(val); builder.Append(","); } ); outcome = builder.ToString(); outcome = outcome.Substring(0, outcome.Length - 1); }); Console.WriteLine(outcome); Console.ReadKey(); }
结果1. String.Join
– 2. StringBuilder + SubString
。 ####ms (ticks)
在这种情况下, String.Join
更快,但如果你可以使用尾随,
那么
StringBuilder
稍快(带尾随)。
我尝试使用StrignBuilder的这个adhoc实现比String.Join更快。 不仅仅是String.Join是一个MEMORY HOG。 当我的实现完成时,我尝试使用20000000字符串并且String.Join总是提供OutOfMemory。 在你的机器上如果你的内存少于8Gb,它甚至可以在更少的字符串上。 评论其中一个要测试的实现。 除非您使用固定的string []数组,否则这是正确的。 String.Join在那里很好。
public static void Main(string[] Args) { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; List strings = new List () {}; for (double d = 0; d < 8000000; d++) { strings.Add(d.ToString()); } TimeSpan upTime; TimeSpan newupTime; using (var pc = new PerformanceCounter("System", "System Up Time")) { StringBuilder sb = new StringBuilder(strings.Count); int i; pc.NextValue(); //The first call returns 0, so call this twice upTime = TimeSpan.FromSeconds(pc.NextValue()); for (i = 0; i < strings.Count - 1; i++) { sb.Append(strings[i]); sb.Append(","); } sb.Append(strings[i]); newupTime = TimeSpan.FromSeconds(pc.NextValue()); sb = null; Console.WriteLine("SB " + (newupTime - upTime).TotalMilliseconds); } using (var pc = new PerformanceCounter("System", "System Up Time")) { pc.NextValue(); upTime = TimeSpan.FromSeconds(pc.NextValue()); string s = string.Join(",", strings); newupTime = TimeSpan.FromSeconds(pc.NextValue()); Console.WriteLine("JOIN " + (newupTime - upTime).TotalMilliseconds); } } SB 406 JOIN 484
如果想要冷却并使用重燃料运行使用聚合物
List stringList = new List { "1234567890", "34343434", "4343434" }; Console.WriteLine( stringList.Aggregate( ( current, next ) => string.Format( "{0}, {1}", current, next ) ) ); // Outputs: 1234567890, 34343434, 4343434