Comment construire une std::string à partir d'un std::vector<string>?
J'aimerais construire un std::string
à partir d'un std::vector<std::string>
.
Je pourrais utiliser std::stringsteam
, mais imaginez, il y a une façon plus simple:
std::string string_from_vector(const std::vector<std::string> &pieces) {
std::stringstream ss;
for(std::vector<std::string>::const_iterator itr = pieces.begin();
itr != pieces.end();
++itr) {
ss << *itr;
}
return ss.str();
}
Sinon, comment pourrais-je faire cela?
Peut-être
std::string res; for (...) { res += *it; }
?OriginalL'auteur WilliamKF | 2013-03-11
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser le
std::accumulate()
fonction standard de la<numeric>
en-tête (cela fonctionne, car une surcharge deoperator +
est défini pourstring
s qui retourne la concaténation de ses deux arguments):Sinon, vous pouvez utiliser un plus efficace, petit
for
cycle:Ouais, en gros les deux réponses sont correctes 🙂
Mignon, mais négligent. Il va allouer une nouvelle chaîne pour chaque opération, car il utilise
operator+
et génère une nouvelle chaîne, au lieu deoperator+=
pour en modifier un existant.J'ai écrit une bibliothèque à l'aide de laquelle il serait juste
s = v | sum();
qui utilise en interne+=
au lieu de+
😉Correct. J'ai mis à jour ma réponse
OriginalL'auteur Andy Prowl
C++03
C++11 (MSVC 2010 sous-ensemble)
C++11
Ne pas utiliser
std::accumulate
pour la concaténation de chaîne, c'est un classique Schlemiel l'algorithme du Peintre, pire que celle de l'exemple habituel à l'aide destrcat
dans C. Sans C++11 sémantique de déplacement, il engage deux copies inutiles de l'accumulateur pour chaque élément du vecteur. Même avec la sémantique de déplacement, il y aura toujours un inutile copie de l'accumulateur pour chaque élément.Les trois exemples ci-dessus sont O(n).
std::accumulate
est O(n2) pour les chaînes.C++20
Dans le projet actuel de ce qui est attendu de devenir C++20, la définition de
std::accumulate
a été modifié à utiliserstd::move
lors de l'ajout de l'accumulateur, donc à partir de C++20 partir,accumulate
sera O(n) pour les cordes, et peut être utilisé comme un one-liner:OriginalL'auteur Oktalist
Pourquoi ne pas simplement utiliser l'opérateur + pour les ajouter ensemble?
std::accumulate utilise std::plus sous le capot par défaut, et l'ajout de deux chaînes de concaténation en C++, l'opérateur + est surchargé pour les std::string.
to_string
au lieu destring_from_vector
.Je n'aurais probablement trop, mais c'est le nom qui a été utilisé dans la question d'origine.
OriginalL'auteur bstamour
Mon choix personnel serait la gamme à base de boucle, comme dans Oktalist réponse.
Boost offre également une belle solution:
Cette affiche:
En tout cas, je trouve le
std::accumulate()
approche d'une mauvaise utilisation de cet algorithme (quelle que soit la complexité des questions).OriginalL'auteur Ali
Un peu en retard à la fête, mais j'ai aimé le fait que nous pouvons utiliser initialiseur de listes:
Alors vous pouvez simplement invoquer (Python style):
std::initializer_list
au lieu d'unstd::vector
? Aussi, je ne pense pas que vous avez besoin de faire une copie du vecteur pourrait passer par référence const.les deux initlist ou vecteurs sont mauvais. quelles sont les fonctions de travail avec les collections doivent prendre l'aire. par application de duck-typing principe, l'exigence minimale de principe et principe de découplage.
qu'entendez-vous par "plages" dans ce contexte?
href="https://ericniebler.github.io/range-v3/" >ericniebler.github.io/gamme-v3
oui, et c'est le choix fait par la bibliothèque standard du comité. Vous trouverez toutes les fonctions ici en.cppreference.com/w/cpp/algorithm se conformer à la "les deux itérateurs" modèle. Et probablement va être porté à la plage en C++20.
OriginalL'auteur Benjamin K.
Google Rappel a la fonction asbl::StrJoin qui fait ce que vous avez besoin.
Exemple de leur l'en-tête fichier.
Notez que le séparateur peut être aussi
""
OriginalL'auteur NoSenseEtAl
Avec c++11 la stringstream chemin n'est pas trop effrayant:
for (auto &i: v) { s << i; }
au lieu de la for_each ligne?Pourquoi utiliser un stringstream à tous? Faire
s
une chaîne, et faire le lambda{ s += elem }
non! c'est le schoolbook exemple de Schlemiel le peintre pessimization. joelonsoftware.com/2001/12/11/back-to-basics
Ce n'est pas un Schlemiel le peintre, comme
std::string
sait de sa propre longueur. Il n'a pas à effectuer une itération surs
de trouver le terminateur null. Elle pourrait être améliorée, même si, en utilisantstd::string::reserve
d'éviter la répétition des allocations pours
. Voir aussi mon top-voté (mais pas acceptées) réponse ci-dessus.J'ai aussi upvoted votre réponse, c'est génial. Mais "sait que sa propre taille" ne semble pas être garanti stackoverflow.com/a/256309/893406
OriginalL'auteur PSIAlt