Il existe actuellement des moyens de concaténer ou de fusionner deux vecteurs avec une fonction.
Mais, il semble qu'il n'y ait aucun moyen de concaténer ou de fusionner plus de trois vecteurs avec une fonction.
Par exemple,
vector<string> a = {"a", "b"}; vector<string> b = {"c", "d"}; vector<string> c = {"e", "f"}; vector<string> d = {"g", "h"}; // newVector has to include {"a", "b", "c", "d", "e", "f", "g", "h"} vector<string> newVector = function(a, b, c, d);
S'il n'y en a pas, il semble que cela puisse être implémenté en utilisant un modèle variadic .
Mais, je peux n'imaginez pas comment il peut être implémenté par un modèle variadique .
Existe-t-il des solutions?
3 Réponses :
Voici la solution avec les modèles variadiques
vector<string> newVector; newVector.reserve(a.size()+b.size()+c.size()+d.size()); appendVector(newVector, a, b, c, d);
Il vous suffit d'ajouter vos vecteurs:
template<typename T, typename ...Args> void appendVector(vector<T>& v1, vector<T>& v2, Args... args) { v1.insert(v1.end(), v2.begin(), v2.end()); appendVector(v1, args...); } template<typename T> void appendVector(vector<T>& v1, vector<T>& v2) { v1.insert(v1.end(), v2.begin(), v2.end()); }
p >
En guise d'optimisation, existe-t-il un moyen de permettre à cette approche de préallouer la taille finale du vecteur cible avec reserve ()
avant d'insérer les vecteurs d'entrée? Ce serait bien si le vecteur cible n'avait pas à potentiellement repousser sa capacité sur chaque insert.
De plus, sauf si je lis ce code de manière incorrecte, ce code ne modifie-t-il pas les vecteurs d'entrée lorsque plus d'un vecteur d'entrée est ajouté? Ce ne serait probablement pas un effet secondaire souhaitable.
@RemyLebeau merci d'avoir vérifié les effets secondaires. C'est corrigé maintenant. En ce qui concerne reserve ()
, je ne suis pas vraiment sûr de son efficacité.
Vous pouvez même supprimer l'appel récursif et calculer la taille de la réservation dans la fonction Démo en C ++ 17 a >
Essayez quelque chose comme ceci:
std::vector<std::string> a = {"a", "b"}; std::vector<std::string> b = {"c", "d"}; std::vector<std::string> c = {"e", "f"}; std::vector<std::string> d = {"g", "h"}; std::vector<std::string> newVector = merge({std::cref(a), std::cref(b), std::cref(c), std::cref(d)});
template<typename T> std::vector<T> merge(std::initializer_list<std::reference_wrapper<const std::vector<T>>> vecs) { size_t size = 0; for(auto &v : vecs) { size += v.get().size(); } std::vector<T> ret; ret.reserve(size); for(auto &v : vecs) { ret.insert(ret.end(), v.get().begin(), v.get().end()); } return ret; }
Alternativement:
std::vector<std::string> a = {"a", "b"}; std::vector<std::string> b = {"c", "d"}; std::vector<std::string> c = {"e", "f"}; std::vector<std::string> d = {"g", "h"}; std::vector<std::string> newVector = merge({&a, &b, &c, &d});
template<typename T> std::vector<T> merge(std::initializer_list<std::vector<T>*> vecs) { size_t size = 0; for(auto v : vecs) { size += v->size(); } std::vector<T> ret; ret.reserve(size); for(auto v : vecs) { ret.insert(ret.end(), v->begin(), v->end()); } return ret; }
Je ne suis pas sûr des modèles variadiques, qu'en est-il juste de
pour (auto v: {a, b, c, d}) {newVector.insert (newVector.end (), v.begin (), v.end ()); }
? Ce n'est que 3 lignes de code et ce qui se passe est assez clair@Tas Merci, c'est la solution intéressante. Mais pourrais-je le fonctionnaliser, en supposant que le type de vecteur peut être quelque chose comme int, double (fusionnant les mêmes types de vecteur)
@sungjuncho une chose à surveiller à propos de
{a, b, c, d}
est qu'il fait une copie dea
,b
, etc. Vous pouvez utiliser{& a, & b, & c, & d}
pour contourner cela. Voir ma réponse pour un exemple fonctionnalisé de ceci