Concaténation de deux std:: vecteurs
17 réponses
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
si vous utilisez C++11, et que vous souhaitez déplacer les éléments plutôt que de simplement les copier, Vous pouvez utiliser std:: move_iterator ( http://en.cppreference.com/w/cpp/iterator/move_iterator ) avec insertion (ou copie):
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<int> dest{1,2,3,4,5};
std::vector<int> src{6,7,8,9,10};
// Move elements from src to dest.
// src is left in undefined but safe-to-destruct state.
dest.insert(
dest.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end())
);
// Print out concatenated vector.
std::copy(
dest.begin(),
dest.end(),
std::ostream_iterator<int>(std::cout, "\n")
);
return 0;
}
ce ne sera pas plus efficace pour l'exemple avec les ints, car les déplacer n'est pas plus efficace que de les copier, mais pour une structure de données avec des mouvements optimisés, il peut éviter de copier l'état inutile:
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char** argv) {
std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
std::vector<std::vector<int>> src{{6,7,8,9,10}};
// Move elements from src to dest.
// src is left in undefined but safe-to-destruct state.
dest.insert(
dest.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end())
);
return 0;
}
après le déplacement, l'élément src est laissé dans un état indéfini mais sûr à détruire, et ses anciens éléments ont été transférés directement au nouvel élément de la dest à la fin.
j'utiliserais la fonction insert , quelque chose comme:
vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
ou vous pouvez utiliser:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
Ce modèle est utile si les deux vecteurs ne contiennent pas exactement le même type de chose, parce que vous pouvez utiliser quelque chose à la place de std::back_inserter pour passer d'un type à l'autre.
avec C++11, je préfère ajouter le vecteur b À a:
std::move(b.begin(), b.end(), std::back_inserter(a));
lorsque a
et b
ne sont pas superposés, et b
ne sera plus utilisé.
std::vector<int> first;
std::vector<int> second;
first.insert(first.end(), second.begin(), second.end());
je préfère un qui est déjà mentionné:
a.insert(a.end(), b.begin(), b.end());
mais si vous utilisez C++11, Il y a une autre façon générique:
a.insert(std::end(a), std::begin(b), std::end(b));
aussi, ne fait pas partie d'une question, mais il est conseillé d'utiliser reserve
avant d'Ajouter pour une meilleure performance. Et si vous êtes vecteur concaténateur avec lui-même, sans réserver il échoue, donc vous devriez toujours reserve
.
Donc, fondamentalement, ce que vous avez besoin de:
template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
a.reserve(a.size() + b.size());
a.insert(a.end(), b.begin(), b.end());
}
vous devez utiliser vecteur:: insérer
v1.insert(v1.end(), v2.begin(), v2.end());
si vous êtes intéressé par une garantie d'exception forte (lorsque le constructeur de copie peut lancer une exception):
template<typename T>
inline void append_copy(std::vector<T>& v1, const std::vector<T>& v2)
{
const auto orig_v1_size = v1.size();
v1.reserve(orig_v1_size + v2.size());
try
{
v1.insert(v1.end(), v2.begin(), v2.end());
}
catch(...)
{
v1.erase(v1.begin() + orig_v1_size, v1.end());
throw;
}
}
similaire append_move
avec une forte garantie ne peut pas être mis en œuvre en général si le constructeur de mouvement de vector element peut lancer (ce qui est peu probable mais quand même).
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
ajoutez celui-ci à votre fichier d'en-tête:
template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
vector<T> ret = vector<T>();
copy(a.begin(), a.end(), back_inserter(ret));
copy(b.begin(), b.end(), back_inserter(ret));
return ret;
}
et l'utiliser de cette façon:
vector<int> a = vector<int>();
vector<int> b = vector<int>();
a.push_back(1);
a.push_back(2);
b.push_back(62);
vector<int> r = concat(a, b);
R contiendra [1,2,62]
Voici une solution polyvalente utilisant la sémantique de déplacement C++11:
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
if (lhs.empty()) return rhs;
if (rhs.empty()) return lhs;
std::vector<T> result {};
result.reserve(lhs.size() + rhs.size());
result.insert(result.cend(), lhs.cbegin(), lhs.cend());
result.insert(result.cend(), rhs.cbegin(), rhs.cend());
return result;
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
return std::move(lhs);
}
template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
return std::move(rhs);
}
template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& rhs)
{
if (lhs.empty()) return std::move(rhs);
lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
return std::move(lhs);
}
noter En quoi cela diffère de append
ing à un vector
.
Un général boost de performance pour concaténer est de vérifier la taille des vecteurs. Et fusionner / insérer le plus petit avec le plus grand.
//vector<int> v1,v2;
if(v1.size()>v2.size()){
v1.insert(v1.end(),v2.begin(),v2.end());
}else{
v1.insert(v2.end(),v1.begin(),v1.end());
}
, Vous pouvez préparer votre propre modèle pour opérateur+:
template <typename T>
inline T operator+(const T & a, const T & b)
{
T res = a;
res.insert(res.end(), b.begin(), b.end());
return res;
}
la Prochaine chose -+:
vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
cout << x << " ";
cout << endl;
cet exemple donne la sortie:
1 2 3 4 5 6 7 8
si ce que vous recherchez est une façon d'ajouter un vecteur à un autre après la création, vector::insert
est votre meilleur pari, comme cela a été répondu plusieurs fois, par exemple:
vector<int> first = {13};
const vector<int> second = {42};
first.insert(first.end(), second.cbegin(), second.cend());
malheureusement il n'y a aucun moyen de construire un const vector<int>
, comme ci-dessus vous devez construire et puis insert
.
Si ce que vous cherchez est un conteneur pour la concaténation de ces deux vector<int>
s, il peut y avoir quelque chose de mieux disponible pour vous, si:
- votre
vector
contient des primitives - vos primitives contenues sont de taille 32-bit ou plus petit
- vous voulez un
const
conteneur
si tout ce qui précède est vrai, je suggère d'utiliser le basic_string
qui est char_type
correspond à la taille de la primitive contenue dans votre vector
. Vous devez inclure un static_assert
dans votre code pour valider ces tailles rester cohérent:
static_assert(sizeof(char32_t) == sizeof(int));
Avec cette tenue de vrai, vous pouvez le faire:
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
pour plus d'informations sur les différences entre string
et vector
vous pouvez regarder ici: https://stackoverflow.com/a/35558008/2642059
pour un exemple en direct de ce code vous pouvez regarder ici: http://ideone.com/7Iww3I
pour être honnête, vous pourriez concaténer rapidement deux vecteurs par des éléments de copie de deux vecteurs dans l'autre ou tout simplement ajouter un de deux vecteurs!. Cela dépend de votre objectif.
Méthode 1: Attribuer un nouveau vecteur avec sa taille est la somme de deux vecteurs de taille.
vector<int> concat_vector = vector<int>();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector
Méthode 2: ajouter le vecteur A en ajoutant / insérant des éléments du vecteur B.
// Loop for insert elements of vector_B into vector_A with insert()
function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());