161

私はこれまでこれに遭遇したことはありませんが、今では、をに変換する本当に簡単な方法が見つからないことに驚いていIEnumerable<char>ますstring

私が考えることができる最善の方法はですstring str = new string(myEnumerable.ToArray());が、私には、これは新しいものchar[]を作成し、それから新しいものを作成するstringように思えます。これは高価に思えます。

これは、.NETFrameworkのどこかに組み込まれている一般的な機能だと思いました。これを行うためのより簡単な方法はありますか?

興味のある方のために、これを使用したい理由は、LINQを使用して文字列をフィルタリングするためです。

string allowedString = new string(inputString.Where(c => allowedChars.Contains(c)).ToArray());
4

6 に答える 6

170

を使用できますString.Concat()

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

警告:このアプローチには、パフォーマンスに影響があります。 String.Concat文字の特殊なケースのコレクションではないため、すべての文字が文字列に変換され、ドキュメントに記載されているように連結されたかのように機能します(実際にはそうなります)。確かに、これにより、このタスクを実行するための組み込みの方法が提供されますが、より適切に実行できる可能性があります。

フレームワーク内に特別な場合の実装はないと思うので、実装charする必要があります。文字列ビルダーに文字を追加する単純なループは、作成するのに十分簡単です。


これが私が開発マシンで取ったいくつかのベンチマークであり、それはほぼ正しいように見えます。

32ビットリリースビルドの300文字シーケンスでの1000000回の反復:

ToArrayString:00:00:03.1695463
コンカット: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();
}
于 2012-07-25T16:19:34.370 に答える
88

.NetCore2.1のリリース用に編集

.Net Core 2.1のリリースのテストを繰り返すと、次のような結果が得られます。

「Concat」の1000000回の反復には842msかかりました。

「新しい文字列」の1000000回の反復には1009ミリ秒かかりました。

「sb」の1000000回の反復には902msかかりました。

つまり、.Net Core 2.1以降を使用している場合は、それが重要Concatです。

詳細については、 MSのブログ投稿を参照してください。


私はこれを別の質問の主題にしましたが、ますます、それはこの質問への直接の答えになりつつあります。

をに変換する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();

私のテストでは、これはリンクされた質問で詳しく説明されています。1000000繰り返しの場合、次の"Some reasonably small test data"ような結果が得られます。

「Concat」の1000000回の反復には1597msかかりました。

「新しい文字列」の1000000回の反復には869ミリ秒かかりました。

「StringBuilder」の1000000回の反復には748ミリ秒かかりました。

string.Concatこれは、このタスクに使用する正当な理由がないことを私に示唆しています。シンプルにしたい場合は新しい文字列アプローチを使用し、パフォーマンスが必要な場合はStringBuilderを使用します。

私は自分の主張に注意します。実際には、これらの方法はすべて正常に機能し、これはすべて最適化を超えている可能性があります。

于 2013-02-11T12:37:28.853 に答える
22

.NET 4以降、多くの文字列メソッドは引数としてIEnumerableを取ります。

string.Concat(myEnumerable);
于 2012-07-25T16:19:38.350 に答える
11

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

だから、あなたがアキュムレータのファンなら、ここに行きます。

于 2014-10-24T04:31:14.653 に答える
10

私のデータは、ジョドレルが投稿した結果とは反対です。まず、私が使用している拡張メソッドを見てみましょう。

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

結果

  • コンキャット:1x
  • 新規:3倍
  • StringBuilder:3x

入力

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

結果

  • コンキャット:1x
  • 新規:7倍
  • StringBuilder:7x

入力

  • ((IEnumerable<char>)RandomString(STRLEN)) (これは単なるアップキャストです)

結果

  • コンキャット:0ミリ秒
  • 新規:2000ミリ秒
  • StringBuilder:2000ミリ秒
  • ダウンキャスト:0ミリ秒

これは、.NETFramework3.5をターゲットとするInteli5760で実行しました。

于 2013-07-03T22:07:07.007 に答える
10

別の可能性は使用しています

string.Join("", myEnumerable);

パフォーマンスは測定しませんでした。

于 2014-08-21T13:21:22.857 に答える