IEnumable < char > 到 string

我以前从来没有碰到过这种情况,但是我现在碰到了,而且很惊讶我不能找到一种真正简单的方法来将 IEnumerable<char>转换成 string

我能想到的最好的方法是 string str = new string(myEnumerable.ToArray());,但是,对我来说,这似乎会创建一个新的 char[],然后从中创建一个新的 string,这似乎很昂贵。

我原以为这是内置在。NET 框架的地方。还有更简单的方法吗?

对于那些感兴趣的人,我之所以要使用它是为了使用 LINQ 来过滤字符串:

string allowedString = new string(inputString.Where(c => allowedChars.Contains(c)).ToArray());
105504 次浏览

你可以使用 String.Concat()

var allowedString = String.Concat(
inputString.Where(c => allowedChars.Contains(c))
);

警告 : 此方法将具有一些性能影响。String.Concat没有特殊的字符大小写集合,因此它的执行方式就好像每个字符都被转换成一个字符串,然后连接成上面提到的 在文件中(一个 href = “ http://Referencesource.microsoft.com/# mscolib/system/string.cs,3101”rel = “ noReferrer”,它实际上是这样做的)。当然,这给了你一个内置的方式来完成这项任务,但它可以做得更好。

我不认为在这个框架中有任何特殊情况下的 char实现,所以您必须实现它。将字符附加到字符串生成器的简单循环很容易创建。


下面是我在开发机器上做的一些基准测试,它看起来是正确的。

1000000次对32位发布版本上的300个字符序列的迭代:

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

从.NET4开始,许多字符串方法都使用 IEnumable 作为参数。

string.Concat(myEnumerable);

为.Net Core 2.1的发布而编辑

重复测试.Net Core 2.1的发布,我得到了这样的结果

1000000次的“ Concat”迭代花费了842毫秒。

“新字符串”的1000000次迭代花费了1009ms。

“ sb”的1000000次迭代用了902毫秒。

简而言之,如果您正在使用.Net Core 2.1或更高版本,那么 Concat就是王者。

有关详细信息,请参阅 微软博客文章


我已经把这个作为 另一个问题的主题,但是越来越多,这正在成为这个问题的直接答案。

我已经做了一些性能测试的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();

在我的测试中,这在 相关的问题中有详细说明,对于 "Some reasonably small test data"1000000迭代,我得到的结果是这样的,

“ Concat”的1000000次迭代花费了1597毫秒。

“新字符串”的1000000次迭代花费了869毫秒。

“ StringBuilder”的1000000次迭代花费了748ms。

这对我来说意味着没有很好的理由使用 string.Concat来完成这个任务。如果想要简单,可以使用 新绳子方法; 如果想要性能,可以使用 StringBuilder

我会告诫我的断言,在实践中,所有这些方法都工作得很好,这可能都是过度优化。

我的数据与 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
  • 迭代 = 1000000

输入

  • ((IEnumerable<char>)RandomString(STRLEN)).Reverse()

结果

  • 联合: 1倍
  • 新: 3倍
  • StringBuilder: 3倍

输入

  • ((IEnumerable<char>)RandomString(STRLEN)).Take((int)ITERATIONS/2)

结果

  • 联合: 1倍
  • 新: 7倍
  • StringBuilder: 7倍

输入

  • ((IEnumerable<char>)RandomString(STRLEN)) (这只是一个抛物线)

结果

  • 连接: 0毫秒
  • 新增: 2000毫秒
  • StringBuilder: 2000 ms
  • 直播: 0毫秒

我在一台针对.NET Framework 3.5的英特尔 i5760上运行了这个程序。

另一种可能性是使用

string.Join("", myEnumerable);

我没有衡量表现。

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

所以,如果你是蓄电池的爱好者,那么这就是了。