Оскільки я люблю однокласні вкладиші (вони дуже корисні для всяких дивних речей, як ви побачите в кінці), ось рішення, яке використовує std :: accumulate та лямбда-програму C ++ 11:
std::accumulate(alist.begin(), alist.end(), std::string(),
[](const std::string& a, const std::string& b) -> std::string {
return a + (a.length() > 0 ? "," : "") + b;
} )
Я вважаю цей синтаксис корисним для оператора потоку, де я не хочу, щоб всі види дивної логіки виходили за рамки операції потоку, а лише для простого об'єднання рядків. Розглянемо, наприклад, цей оператор return із методу, який форматує рядок за допомогою операторів потоку (за допомогою 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();
Оновлення:
Як зазначав @plexando в коментарях, наведений вище код страждає від неправильної поведінки, коли масив починається з порожніх рядків через те, що в перевірці на "перший запуск" відсутні попередні прогони, які не призвели до додаткових символів, а також - дивно запускати перевірку на "перший запуск" на всіх прогонах (тобто код недостатньо оптимізований).
Рішення обох цих проблем є простим, якщо ми точно знаємо, що список містить принаймні один елемент. ОТО, якщо ми точно знаємо, що список не має хоча б одного елемента, тоді ми можемо ще більше скоротити цикл.
Я думаю, що отриманий код не такий гарний, тому я додаю його сюди як Правильне рішення , але я думаю, що обговорення вище все-таки має merrit:
alist.empty() ? "" :
++alist.begin(), alist.end(),
*alist.begin(),
[](auto& a, auto& b) { return a + "," + b; });
Примітки:
- Для контейнерів, що підтримують прямий доступ до першого елемента, можливо, краще використовувати це для третього аргументу, а не
alist[0]
для векторів.
- Відповідно до обговорення в коментарях та чаті, лямбда все ще виконує копіювання. Це можна звести до мінімуму, використовуючи замість цього (менш красиву) лямбду:
[](auto&& a, auto&& b) -> auto& { a += ','; a += b; return a; })
яка (на GCC 10) покращує продуктивність більш ніж на x10. Дякую @Deduplicator за пропозицію. Я все ще намагаюся зрозуміти, що тут відбувається.