4
votes

Existe-t-il un moyen de concaténer plusieurs vecteurs simplement?

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 commentaires

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 de a , b , etc. Vous pouvez utiliser {& a, & b, & c, & d} pour contourner cela. Voir ma réponse pour un exemple fonctionnalisé de ceci


3 Réponses :


3
votes

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 >


4 commentaires

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



5
votes

Si vous pouvez utiliser range v3 , vous pouvez simplement le faire:

std::vector<std::string> allVec = ranges::view::concat(a, b, c, d);

Voir démo ici .

Vous pouvez l'utiliser avec n'importe quel type de vecteur.


0 commentaires

2
votes

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;
}

Démo en direct

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;
}

Démo en direct


0 commentaires