Da ich Einzeiler liebe (sie sind sehr nützlich für alle Arten von seltsamen Dingen, wie Sie am Ende sehen werden), gibt es hier eine Lösung mit std :: accumulate und C ++ 11 lambda:
std::accumulate(alist.begin(), alist.end(), std::string(),
[](const std::string& a, const std::string& b) -> std::string {
return a + (a.length() > 0 ? "," : "") + b;
} )
Ich finde diese Syntax nützlich für Stream-Operatoren, bei denen ich nicht alle Arten von seltsamer Logik außerhalb des Bereichs der Stream-Operation haben möchte, nur um einen einfachen String-Join durchzuführen. Betrachten Sie zum Beispiel diese return-Anweisung von einer Methode, die eine Zeichenfolge mithilfe von Stream-Operatoren (mithilfe von std;) formatiert:
return (dynamic_cast<ostringstream&>(ostringstream()
<< "List content: " << endl
<< std::accumulate(alist.begin(), alist.end(), std::string(),
[](const std::string& a, const std::string& b) -> std::string {
return a + (a.length() > 0 ? "," : "") + b;
} ) << endl
<< "Maybe some more stuff" << endl
)).str();
Aktualisieren:
Wie von @plexando in den Kommentaren hervorgehoben, weist der obige Code ein Fehlverhalten auf, wenn das Array mit leeren Zeichenfolgen beginnt, da bei der Prüfung auf "erster Lauf" frühere Läufe fehlen, die zu keinen zusätzlichen Zeichen geführt haben, und außerdem - Es ist seltsam, bei allen Läufen nach "wird zuerst ausgeführt" zu suchen (dh der Code ist unteroptimiert).
Die Lösung für diese beiden Probleme ist einfach, wenn wir wissen, dass die Liste mindestens ein Element enthält. OTOH, wenn wir sicher wissen, dass die Liste nicht mindestens ein Element enthält, können wir den Lauf noch weiter verkürzen.
Ich denke, der resultierende Code ist nicht so hübsch, also füge ich ihn hier als The Correct Solution hinzu , aber ich denke, die obige Diskussion hat immer noch Merrit:
alist.empty() ? "" :
++alist.begin(), alist.end(),
*alist.begin(),
[](auto& a, auto& b) { return a + "," + b; });
Anmerkungen:
- Für Container, die den direkten Zugriff auf das erste Element unterstützen, ist es wahrscheinlich besser, dies stattdessen für das dritte Argument zu verwenden, also
alist[0]
für Vektoren.
- Gemäß der Diskussion in den Kommentaren und im Chat kopiert das Lambda immer noch. Dies kann minimiert werden, indem stattdessen dieses (weniger hübsche) Lambda verwendet wird,
[](auto&& a, auto&& b) -> auto& { a += ','; a += b; return a; })
das (bei GCC 10) die Leistung um mehr als x10 verbessert. Vielen Dank an @Deduplicator für den Vorschlag. Ich versuche immer noch herauszufinden, was hier los ist.