我以前从来没有偶然发现过这个问题,但我现在感到很惊讶,我找不到将IEnumerable<char>
转换为string
的简单方法。
我能想到的最好的方法是string str = new string(myEnumerable.ToArray());
,但是,对我来说,似乎这会创建一个新的char[]
,然后从中创建一个新的string
,看起来很贵。
我认为这将是.NET框架内置的常用功能。有更简单的方法吗?
对于那些感兴趣的人,我想使用它的原因是使用LINQ来过滤字符串:
string allowedString = new string(inputString.Where(c => allowedChars.Contains(c)).ToArray());
答案 0 :(得分:129)
您可以使用String.Concat()
。
var allowedString = String.Concat(
inputString.Where(c => allowedChars.Contains(c))
);
警告:这种方法会产生一些性能影响。 String.Concat
不是字符的特殊情况集合,因此它的表现就好像每个字符都转换为字符串,然后按照in the documentation( and it actually does )连接起来。当然,这为您提供了完成此任务的内置方法,但可以做得更好。
我认为框架中没有任何特殊情况char
的实现,所以你必须实现它。将字符附加到字符串构建器的简单循环非常简单,可以创建。
这是我在开发机器上采用的一些基准测试,看起来是正确的。
在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();
}
答案 1 :(得分:71)
编辑发布.Net Core 2.1
重复测试.Net Core 2.1的发布,我得到了这样的结果
“Concat”的1000000次迭代耗时842ms。
1000000次“new String”迭代耗时1009ms。
“sb”的1000000次迭代耗时902ms。
简而言之,如果您使用.Net Core 2.1或更高版本,则Concat
为王。
有关详细信息,请参阅MS blog post。
我已将此作为another question的主题,但越来越多,这正在成为这个问题的直接答案。
我已经对3种将IEnumerable<char>
转换为string
的简单方法进行了一些性能测试,这些方法是
新字符串
return new string(charSequence.ToArray());
<强>的毗连强>
return string.Concat(charSequence)
<强>的StringBuilder 强>
var sb = new StringBuilder();
foreach (var c in charSequence)
{
sb.Append(c);
}
return sb.ToString();
在我的测试中,详细信息在linked question中,针对1000000
的{{1}}次迭代,我得到了这样的结果,
“Concat”的1000000次迭代耗时1597ms。
“新字符串”的1000000次迭代耗时869ms。
“StringBuilder”的1000000次迭代耗时748ms。
这告诉我,没有充分的理由使用"Some reasonably small test data"
来执行此任务。如果您想要简单,请使用 new string 方法,如果想要性能,请使用 StringBuilder 。
我会告诫我的断言,在实践中所有这些方法都运行良好,这可能都是过度优化。
答案 2 :(得分:17)
从.NET 4开始,许多字符串方法将IEnumerable视为参数。
string.Concat(myEnumerable);
答案 3 :(得分:10)
我的数据与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();
}
。通过强>
<强>输入强>
((IEnumerable<char>)RandomString(STRLEN)).Reverse()
<强>结果
<强>输入强>
((IEnumerable<char>)RandomString(STRLEN)).Take((int)ITERATIONS/2)
<强>结果
<强>输入强>
((IEnumerable<char>)RandomString(STRLEN))
(这只是一个向上) <强>结果
我在面向.NET Framework 3.5的Intel i5 760上运行此功能。
答案 4 :(得分:10)
另一种可能性是使用
string.Join("", myEnumerable);
我没有衡量表现。
答案 5 :(得分:9)
以下是StringBuilder答案的更简洁版本:
return charSequence.Aggregate(new StringBuilder(), (seed, c) => seed.Append(c)).ToString();
我使用Jeff Mercado使用的相同测试进行计时,并且在相同的300字符序列(32位版本构建)上,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();
}
所以,如果你是累积者的粉丝,那么你就去吧。