684 Stimmen

Concateniere alle Zeichenfolgen in einer List<string> mithilfe von LINQ

Gibt es einen einfachen LINQ-Ausdruck, um alle Elemente meiner gesamten List-Sammlung zu einem einzelnen string mit einem Trennzeichen zu verkettet?

Was ist, wenn die Sammlung aus benutzerdefinierten Objekten anstelle von string besteht? Stellen Sie sich vor, ich muss auf object.Name verkettet.

45 Stimmen

Warum Linq und nicht string.Join() ?

17 Stimmen

String.Join ist besser, aber ich denke, dass Linq deinen Code Spaß macht, das könnte der Grund sein!

22 Stimmen

String.Join ist besser, weil es einen StringBuilder verwendet und die inhärente O(n^2)-Leistung der wiederholten Verkettung vermeidet.

2voto

Dies Antwort zielt darauf ab, einige Erwähnungen von LINQ-basierten Lösungen zu erweitern und zu verbessern. Es ist kein Beispiel für eine "gute" Lösung an sich. Verwenden Sie einfach string.Join wie vorgeschlagen, wenn es Ihren Bedürfnissen entspricht.

Kontext

Diese Antwort wird durch den zweiten Teil der Frage (einen generischen Ansatz) und einige Kommentare angeregt, die eine tiefe Affinität für LINQ zum Ausdruck bringen.

Angeboten, dass keine Antwort allen diesen Anforderungen entspricht, schlage ich eine Implementierung vor, die auf LINQ basiert, linear ausgeführt wird, mit Enumerierungen beliebiger Länge funktioniert und generische Konvertierungen zu Zeichenfolgelementen unterstützt.

Also, LINQ oder nichts? Okay.
static string Serialize(IEnumerable enumerable, char delim, Func toString)
{
    return enumerable.Aggregate(
        new StringBuilder(),
        (sb, t) => sb.Append(toString(t)).Append(delim),
        sb =>
        {
            if (sb.Length > 0)
            {
                sb.Length--;
            }

            return sb.ToString();
        });
}

Diese Implementierung ist aufwändiger als viele Alternativen, hauptsächlich weil wir die Grenzbedingungen für das Trennzeichen (Separator) in unserem eigenen Code verwalten müssen.

Es sollte in linearer Zeit ausgeführt werden, die Elemente höchstens zweimal durchlaufend.

Einmal zum Generieren aller Zeichenfolgen, die zuerst angehängt werden sollen, und null bis einmal beim Generieren des endgültigen Ergebnisses während des endgültigen ToString-Aufrufs. Dies liegt daran, dass letzteres möglicherweise einfach den Puffer zurückgeben kann, der bereits groß genug war, um alle angehängten Zeichenfolgen enthalten zu können, oder es das volle Ding neu generieren muss (unwahrscheinlich), oder etwas dazwischen. Siehe z. B. Welche ist die Komplexität von StringBuilder.ToString() auf SO für weitere Informationen.

Schlussworte

Verwenden Sie einfach string.Join wie vorgeschlagen, wenn es Ihren Bedürfnissen entspricht, fügen Sie ein Select hinzu, wenn Sie die Sequenz zuerst anpassen müssen.

Der Hauptzweck dieser Antwort besteht darin zu verdeutlichen, dass es möglich ist, die Leistung unter Verwendung von LINQ in Schach zu halten. Das Ergebnis ist (wahrscheinlich) zu ausführlich, um es zu empfehlen, aber es existiert.

1voto

Reza Jenabi Punkte 3356

Sie können Aggregate verwenden, um die Zeichenfolgen in eine einzelne, durch Zeichen getrennte Zeichenfolge zu konkatenieren, aber es wird eine Ungültige Betriebsausnahme ausgelöst, wenn die Sammlung leer ist.

Sie können die Funktion Aggregate mit einer Seed-Zeichenfolge verwenden.

var seed = string.Empty;
var seperator = ",";

var cars = new List() { "Ford", "McLaren Senna", "Aston Martin Vanquish"};

var carAggregate = cars.Aggregate(seed,
                (partialPhrase, word) => $"{partialPhrase}{seperator}{word}").TrimStart(',');

Sie können string.Join verwenden, es ist egal, ob Sie ihm eine leere Sammlung übergeben.

var seperator = ",";

var cars = new List() { "Ford", "McLaren Senna", "Aston Martin Vanquish"};

var carJoin = string.Join(seperator, cars);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X