it-swarm.com.de

IEnumerable <char> to string

Ich bin noch nie darauf gestoßen, aber ich habe es jetzt und bin überrascht, dass ich keine wirklich einfache Möglichkeit finde, einen IEnumerable<char> In einen string umzuwandeln.

Der beste Weg, den ich mir vorstellen kann, ist string str = new string(myEnumerable.ToArray());, aber für mich scheint es, als würde dies einen neuen char[] Und dann daraus einen neuen string erstellen. das scheint teuer.

Ich hätte gedacht, dies wäre eine übliche Funktionalität, die irgendwo in das .NET-Framework integriert ist. Gibt es einen einfacheren Weg, dies zu tun?

Für Interessenten ist der Grund, warum ich dies verwenden möchte, die Verwendung von LINQ zum Filtern von Zeichenfolgen:

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

Sie können String.Concat() verwenden.

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

Einschränkung : Dieser Ansatz hat einige Auswirkungen auf die Leistung. String.Concat enthält keine Sonderfallsammlungen von Zeichen, daher wird so verfahren, als ob jedes Zeichen in eine Zeichenfolge konvertiert und dann wie erwähnt verkettet wurde in der Dokumentation (nd es tut tatsächlich). Sicher, das gibt Ihnen einen eingebauten Weg, um diese Aufgabe zu erfüllen, aber es könnte besser gemacht werden.

Ich glaube nicht, dass es Implementierungen innerhalb des Frameworks gibt, die den Sonderfall char darstellen, also müssen Sie sie implementieren. Eine einfache Schleife, mit der Zeichen an einen Zeichenfolgengenerator angehängt werden, ist einfach zu erstellen.


Hier sind einige Benchmarks, die ich auf einer Entwicklungsmaschine gemacht habe und die ungefähr richtig aussieht.

1000000 Iterationen in einer 300-Zeichen-Sequenz in einem 32-Bit-Release-Build:

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

Bearbeitet für die Veröffentlichung von .Net Core 2.1

Wenn ich den Test für die Veröffentlichung von .Net Core 2.1 wiederhole, erhalte ich die folgenden Ergebnisse

1000000 Iterationen von "Concat" dauerten 842 ms.

1000000 Iterationen von "new String" dauerten 1009 ms.

1000000 Iterationen von "sb" dauerten 902 ms.

Kurz gesagt, wenn Sie .Net Core 2.1 oder höher verwenden, ist Concat König.

Siehe MS-Blogpost für weitere Details.


Ich habe dies zum Thema gemacht eine andere Frage aber immer mehr, das wird eine direkte Antwort auf diese Frage.

Ich habe einige Leistungstests mit 3 einfachen Methoden durchgeführt, um einen IEnumerable<char> In einen string zu konvertieren. Diese Methoden sind

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

In meinen Tests wird dies in der verknüpfte Frage beschrieben. Für 1000000 Iterationen von "Some reasonably small test data" Erhalte ich folgende Ergebnisse:

1000000 Iterationen von "Concat" dauerten 1597 ms.

1000000 Iterationen von "new string" dauerten 869 ms.

1000000 Iterationen von "StringBuilder" dauerten 748 ms.

Dies deutet darauf hin, dass es keinen guten Grund gibt, string.Concat Für diese Aufgabe zu verwenden. Wenn Sie Einfachheit wünschen, verwenden Sie den neuen String Ansatz und wenn Sie Leistung wünschen, verwenden Sie den StringBuilder .

Ich würde meine Behauptung zurückhalten, in der Praxis funktionieren all diese Methoden einwandfrei, und dies könnte alles über die Optimierung hinausgehen.

76
Jodrell

Ab .NET 4 verwenden viele Zeichenfolgemethoden IEnumerable als Argumente.

string.Concat(myEnumerable);
19
MikeP

Meine Daten widersprechen den von Jodrell veröffentlichten Ergebnissen. Schauen Sie sich zuerst die Erweiterungsmethoden an, die ich verwende:

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

Meine Ergebnisse

Mit

  • STRLEN = 31
  • ITERATIONS = 1000000

Eingabe

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

Ergebnisse

  • Concat: 1x
  • Neu: 3x
  • StringBuilder: 3x

Eingabe

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

Ergebnisse

  • Concat: 1x
  • Neu: 7x
  • StringBuilder: 7x

Eingabe

  • ((IEnumerable<char>)RandomString(STRLEN))(das ist nur eine Aufwärtsbewegung)

Ergebnisse

  • Concat: 0 ms
  • Neu: 2000 ms
  • StringBuilder: 2000 ms
  • Downcast: 0 ms

Ich habe dies auf einem Intel i5 760 ausgeführt, der auf .NET Framework 3.5 abzielt.

10
hBGl

Eine andere Möglichkeit ist die Verwendung von

string.Join("", myEnumerable);

Ich habe die Leistung nicht gemessen.

10
nitrogenycs

Hier ist eine prägnantere Version der StringBuilder-Antwort:

return charSequence.Aggregate(new StringBuilder(), (seed, c) => seed.Append(c)).ToString();

Ich habe dies mit denselben Tests wie Jeff Mercado geplant und dies war 1 Sekunde langsamer bei 1.000.000 Iterationen mit derselben 300-Zeichen-Sequenz (32-Bit-Release-Build) als die expliziteren:

static string StringBuilderChars(IEnumerable<char> charSequence)
{
    var sb = new StringBuilder();
    foreach (var c in charSequence)
    {
        sb.Append(c);
    }
    return sb.ToString();
}

Also, wenn Sie ein Fan von Akkus sind, dann sind Sie hier.

9
Adam Smith