IEnumerable <string>string
我从来没有偶然发现过,但我现在很惊讶,我找不到一个真正简单的方法来将IEnumerable<char>
转换为string
。
我能想到的最好的方法是string str = new string(myEnumerable.ToArray());
,但对我来说,似乎这会创build一个新的char[]
,然后从中创build一个新的string
,这看起来很昂贵。
我会认为这将是在.NET框架内build立的通用function。 有一个更简单的方法来做到这一点?
对于那些感兴趣的,我想使用这个的原因是使用LINQ过滤string:
string allowedString = new string(inputString.Where(c => allowedChars.Contains(c)).ToArray());
你可以使用String.Concat()
。
var allowedString = String.Concat( inputString.Where(c => allowedChars.Contains(c)) );
警告 :这种方法会有一些性能影响。 String.Concat
并不是特殊的字符集合,所以它的performance就好像每个字符都被转换成了一个string,然后如文档中提到的那样连接起来( 实际上它是这样的 )。 当然,这给你一个内在的方式来完成这个任务,但它可以做得更好。
我不认为框架中有任何实现将特殊情况char
所以你必须实现它。 将字符附加到string生成器的简单循环很容易创build。
这是我在开发机器上的一些基准,看起来是正确的。
在32位版本上的300字符序列上进行1000000次迭代:
ToArrayString:00:00:03.1695463 Concat:00:00:07.2518054 StringBuilderChars:00:00:03.1335455 StringBuilderStrings:00:00:06.4618266
static readonly IEnumerable<char> seq = Enumerable.Repeat('a', 300); static string ToArrayString(IEnumerable<char> charSequence) { return new String(charSequence.ToArray()); } static string Concat(IEnumerable<char> charSequence) { return String.Concat(charSequence); } static string StringBuilderChars(IEnumerable<char> charSequence) { var sb = new StringBuilder(); foreach (var c in charSequence) { sb.Append(c); } return sb.ToString(); } static string StringBuilderStrings(IEnumerable<char> charSequence) { var sb = new StringBuilder(); foreach (var c in charSequence) { sb.Append(c.ToString()); } return sb.ToString(); }
我已经把这个问题作为另一个问题,但越来越多,这就成为对这个问题的直接回答。
我已经做了一些将IEnumerable<char>
转换为string
的3个简单方法的性能testing,这些方法是
新的string
return new string(charSequence.ToArray());
CONCAT
return string.Concat(charSequence)
StringBuilder的
var sb = new StringBuilder(); foreach (var c in charSequence) { sb.Append(c); } return sb.ToString();
在我的testing中,详细的链接问题 ,对于"Some reasonably small test data"
1000000
次迭代,我得到这样的结果,
“Concat”的1000000次迭代耗时1597ms。
“新string”1000000次迭代耗时869ms。
“StringBuilder”的1000000次迭代耗时748ms。
这暗示了对于这个任务使用string.Concat
没有很好的理由。 如果你想简单的使用新的string方法,如果要性能使用StringBuilder 。
我会告诫我的断言,实际上所有这些方法工作正常,这可能都是过度优化。
从.NET 4开始,许多string方法都以IEnumerable作为参数。
string.Concat(myEnumerable);
我的数据与Jodrell发布的结果相反。 首先看看我使用的扩展方法:
public static string AsStringConcat(this IEnumerable<char> characters) { return String.Concat(characters); } public static string AsStringNew(this IEnumerable<char> characters) { return new String(characters.ToArray()); } public static string AsStringSb(this IEnumerable<char> characters) { StringBuilder sb = new StringBuilder(); foreach (char c in characters) { sb.Append(c); } return sb.ToString(); }
我的结果
同
- STRLEN = 31
- ITERATIONS = 1000000
input
-
((IEnumerable<char>)RandomString(STRLEN)).Reverse()
结果
- Concat:1x
- 新:3倍
- StringBuilder:3x
input
-
((IEnumerable<char>)RandomString(STRLEN)).Take((int)ITERATIONS/2)
结果
- Concat:1x
- 新:7倍
- StringBuilder:7倍
input
-
((IEnumerable<char>)RandomString(STRLEN))
(这只是一个upcast)
结果
- Concat:0 ms
- 新:2000毫秒
- StringBuilder:2000毫秒
- Downcast:0毫秒
我在一个以.NET Framework 3.5为目标的英特尔i5 760上运行这个程序。
这里是一个更简洁的StringBuilder的答案:
return charSequence.Aggregate(new StringBuilder(), (seed, c) => seed.Append(c)).ToString();
我使用Jeff Mercado使用的相同testing对此进行了计时,并且在相同的300个字符序列(32位版本构build版本)上,在1,000,000次迭代中比在更明确的情况下慢了1秒:
static string StringBuilderChars(IEnumerable<char> charSequence) { var sb = new StringBuilder(); foreach (var c in charSequence) { sb.Append(c); } return sb.ToString(); }
所以如果你是蓄电池的粉丝,那么你就去。
另一种可能是使用
string.Join("", myEnumerable);
我没有衡量performance。