Concatenar dos std :: vectores

¿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:

  1. Tu vector contiene primitivos
  2. Sus primitivas contenidas son de tamaño 32 bits o más pequeñas
  3. Quieres un contenedor de 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());