Ponieważ kocham jednolinijki (są bardzo przydatne do wszelkiego rodzaju dziwnych rzeczy, jak zobaczysz na końcu), oto rozwiązanie wykorzystujące std ::umulate i 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;
} )
Uważam, że ta składnia jest przydatna w przypadku operatora strumienia, w którym nie chcę mieć wszelkiego rodzaju dziwnej logiki poza zakresem operacji strumienia, tylko po to, aby wykonać proste łączenie ciągu. Rozważmy na przykład tę instrukcję return from method, która formatuje ciąg przy użyciu operatorów strumienia (using std;):
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();
Aktualizacja:
Jak zauważył @plexando w komentarzach, powyższy kod cierpi na niewłaściwe zachowanie, gdy tablica zaczyna się od pustych ciągów, ponieważ w sprawdzaniu „pierwszego uruchomienia” brakuje poprzednich uruchomień, które nie spowodowały żadnych dodatkowych znaków, a także - dziwne jest uruchamianie sprawdzania „jest uruchamiane jako pierwsze” we wszystkich przebiegach (tj. kod jest niedoptymalizowany).
Rozwiązanie obu tych problemów jest łatwe, jeśli wiemy na pewno, że lista zawiera co najmniej jeden element. OTOH, jeśli wiemy na pewno, że lista nie zawiera przynajmniej jednego elementu, to możemy skrócić przebieg jeszcze bardziej.
Myślę, że wynikowy kod nie jest tak ładny, więc dodaję go tutaj jako The Correct Solution , ale myślę, że powyższa dyskusja nadal ma merrit:
alist.empty() ? "" :
++alist.begin(), alist.end(),
*alist.begin(),
[](auto& a, auto& b) { return a + "," + b; });
Uwagi:
- W przypadku kontenerów, które obsługują bezpośredni dostęp do pierwszego elementu, prawdopodobnie lepiej jest użyć tego dla trzeciego argumentu, a więc
alist[0]
dla wektorów.
- Zgodnie z dyskusją w komentarzach i czacie, lambda nadal kopiuje. Można to zminimalizować, używając zamiast tego tej (mniej ładnej) lambdy:
[](auto&& a, auto&& b) -> auto& { a += ','; a += b; return a; })
która (w GCC 10) poprawia wydajność o więcej niż x10. Dzięki @Deduplicator za sugestię. Nadal próbuję dowiedzieć się, co się tutaj dzieje.