¿Cómo concateno dos std::vector
s?
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
Si está utilizando C ++ 11 y desea mover los elementos en lugar de simplemente copiarlos, puede usar std :: move_iterator ( http://en.cppreference.com/w/cpp/iterator/move_iterator ) junto con la inserción (o copia):
#include #include #include int main(int argc, char** argv) { std::vector dest{1,2,3,4,5}; std::vector 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 (std::cout, "\n") ); return 0; }
Esto no será más eficiente para el ejemplo con ints, ya que moverlos no es más eficiente que copiarlos, pero para una estructura de datos con movimientos optimizados, puede evitar copiar el estado innecesario:
#include #include #include int main(int argc, char** argv) { std::vector> dest{{1,2,3,4,5}, {3,4}}; std::vector> 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; }
Después del movimiento, el elemento de src queda en un estado indefinido pero seguro de destruir, y sus elementos anteriores se transfirieron directamente al nuevo elemento de dest al final.
Usaría la función de inserción , algo así como:
vector a, b; //fill with data b.insert(b.end(), a.begin(), a.end());
O podrías usar:
std::copy(source.begin(), source.end(), std::back_inserter(destination));
Este patrón es útil si los dos vectores no contienen exactamente el mismo tipo de cosa, porque puede usar algo en lugar de std :: back_inserter para convertir de un tipo a otro.
Con C ++ 11, preferiría seguir para anexar el vector b a a:
std::move(b.begin(), b.end(), std::back_inserter(a));
cuando a
y b
no se superponen, y b
ya no se usará más.
std::vector first; std::vector second; first.insert(first.end(), second.begin(), second.end());
Prefiero uno que ya se mencionó:
a.insert(a.end(), b.begin(), b.end());
Pero si usa C ++ 11, hay una forma más genérica:
a.insert(std::end(a), std::begin(b), std::end(b));
Además, no forma parte de una pregunta, pero es aconsejable usar la reserve
antes de agregarla para un mejor rendimiento. Y si está concatenando vector consigo mismo, sin reservarlo falla, por lo que siempre debe reserve
.
Entonces, básicamente, lo que necesitas:
template void Append(std::vector& a, const std::vector & b) { a.reserve(a.size() + b.size()); a.insert(a.end(), b.begin(), b.end()); }
Deberías usar vector :: insert
v1.insert(v1.end(), v2.begin(), v2.end());
Si está interesado en una garantía de excepción fuerte (cuando el constructor de copia puede lanzar una excepción):
template inline void append_copy(std::vector& v1, const std::vector & 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; } }
No se puede implementar un append_move
similar con una garantía fuerte en general si el constructor de movimientos del elemento vectorial puede lanzar (lo cual es poco probable pero aún así).
Con rango v3 , puede tener una concatenación perezosa :
ranges::view::concat(v1, v2)
Demo
vector v1 = {1, 2, 3, 4, 5}; vector v2 = {11, 12, 13, 14, 15}; copy(v2.begin(), v2.end(), back_inserter(v1));
Agregue este a su archivo de encabezado:
template vector concat(vector &a, vector &b) { vector ret = vector (); copy(a.begin(), a.end(), back_inserter(ret)); copy(b.begin(), b.end(), back_inserter(ret)); return ret; }
y úsalo de esta manera:
vector a = vector (); vector b = vector (); a.push_back(1); a.push_back(2); b.push_back(62); vector r = concat(a, b);
r contendrá [1,2,62]
Aquí hay una solución de uso general que usa la semántica de movimientos de C ++ 11:
template std::vector concat(const std::vector & lhs, const std::vector & rhs) { if (lhs.empty()) return rhs; if (rhs.empty()) return lhs; std::vector 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 std::vector concat(std::vector && lhs, const std::vector & rhs) { lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend()); return std::move(lhs); } template std::vector concat(const std::vector & lhs, std::vector && rhs) { rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend()); return std::move(rhs); } template std::vector concat(std::vector && lhs, std::vector && 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); }
Tenga en cuenta cómo esto difiere de append
a un vector
.
Un impulso de rendimiento general para concatenar es verificar el tamaño de los vectores. Y fusiona / inserta el más pequeño con el más grande.
//vector v1,v2; if(v1.size()>v2.size()){ v1.insert(v1.end(),v2.begin(),v2.end()); }else{ v1.insert(v2.end(),v1.begin(),v1.end()); }
Puede preparar su propia plantilla para el operador +:
template inline T operator+(const T & a, const T & b) { T res = a; res.insert(res.end(), b.begin(), b.end()); return res; }
Lo siguiente: solo use +:
vector a{1, 2, 3, 4}; vector b{5, 6, 7, 8}; for (auto x: a + b) cout << x << " "; cout << endl;
Este ejemplo da salida:
1 2 3 4 5 6 7 8
Si lo que estás buscando es una forma de agregar un vector a otro después de la creación, vector::insert
es tu mejor opción, como se ha respondido varias veces, por ejemplo:
vector first = {13}; const vector second = {42}; first.insert(first.end(), second.cbegin(), second.cend());
Lamentablemente, no hay forma de construir un const vector
, como en el ejemplo anterior debes construirlo y luego insert
.
Si lo que realmente está buscando es un contenedor para mantener la concatenación de estos dos vector
s, puede haber algo mejor disponible para usted, si:
vector
contiene primitivos const
Si todo lo anterior es cierto, te sugiero que basic_string
el basic_string
que es de char_type
coincide con el tamaño de la primitiva contenida en tu vector
. Debe incluir un static_assert
en su código para validar que estos tamaños se mantengan consistentes:
static_assert(sizeof(char32_t) == sizeof(int));
Con esto cierto, puedes hacer lo siguiente:
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
Para obtener más información sobre las diferencias entre string
y vector
, puede mirar aquí: https://stackoverflow.com/a/35558008/2642059
Para ver un ejemplo en vivo de este código, puede mirar aquí: http://ideone.com/7Iww3I
Para ser honesto, puedes concatenar rápidamente dos vectores copiando elementos de dos vectores en el otro o solo anexando uno de dos vectores. Depende de tu objective
Método 1: Asignar nuevo vector con su tamaño es la sum del tamaño de dos vectores originales.
vector concat_vector = vector (); concat_vector.setcapacity(vector_A.size() + vector_B.size()); // Loop for copy elements in two vectors into concat_vector
Método 2: agregue el vector A agregando / insertando elementos del vector 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());