Como me encantan las frases ingeniosas (son muy útiles para todo tipo de cosas raras, como verá al final), aquí hay una solución usando std :: acumular y 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;
} )
Encuentro esta sintaxis útil con el operador de flujo, donde no quiero tener todo tipo de lógica extraña fuera del alcance de la operación de flujo, solo para hacer una combinación de cadena simple. Considere, por ejemplo, esta declaración de retorno del método que formatea una cadena usando operadores de flujo (usando 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();
Actualizar:
Como lo señaló @plexando en los comentarios, el código anterior sufre un mal comportamiento cuando la matriz comienza con cadenas vacías debido al hecho de que en la verificación de la "primera ejecución" faltan las ejecuciones anteriores que no han dado como resultado caracteres adicionales, y también - es extraño ejecutar una comprobación de "es la primera ejecución" en todas las ejecuciones (es decir, el código no está optimizado).
La solución para ambos problemas es fácil si sabemos con certeza que la lista tiene al menos un elemento. OTOH, si sabemos con certeza que la lista no tiene al menos un elemento, podemos acortar aún más la ejecución.
Creo que el código resultante no es tan bonito, así que lo agrego aquí como La solución correcta , pero creo que la discusión anterior todavía tiene merrit:
alist.empty() ? "" :
++alist.begin(), alist.end(),
*alist.begin(),
[](auto& a, auto& b) { return a + "," + b; });
Notas:
- Para los contenedores que admiten acceso directo al primer elemento, probablemente sea mejor usarlo para el tercer argumento, es decir,
alist[0]
para los vectores.
- Según la discusión en los comentarios y el chat, el lambda todavía hace algunas copias. Esto se puede minimizar usando esta lambda (menos bonita) en su lugar:
[](auto&& a, auto&& b) -> auto& { a += ','; a += b; return a; })
que (en GCC 10) mejora el rendimiento en más de x10. Gracias a @Deduplicator por la sugerencia. Todavía estoy tratando de averiguar qué está pasando aquí.