vectores unir pseint ordenados mezclar intercalar concatenar cadenas arreglos c++ vector

c++ - unir - ¿Cuál es la mejor manera de concatenar dos vectores?



union de dos vectores en c++ (7)

Estoy usando multitreading y quiero fusionar los resultados. Por ejemplo:

std::vector<int> A; std::vector<int> B; std::vector<int> AB;

Quiero que AB tenga los contenidos de A y los contenidos de B en ese orden. ¿Cuál es la forma más eficiente de hacer algo como esto?


Basado en la respuesta de Kiril V. Lyadvinsky , hice una nueva versión. Este fragmento usa plantilla y sobrecarga. Con él, puedes escribir vector3 = vector1 + vector2 y vector4 += vector3 . Espero que pueda ayudar.

template <typename T> std::vector<T> operator+(const std::vector<T> &A, const std::vector<T> &B) { std::vector<T> AB; AB.reserve( A.size() + B.size() ); // preallocate memory AB.insert( AB.end(), A.begin(), A.end() ); // add A; AB.insert( AB.end(), B.begin(), B.end() ); // add B; return AB; } template <typename T> std::vector<T> &operator+=(std::vector<T> &A, const std::vector<T> &B) { A.reserve( A.size() + B.size() ); // preallocate memory without erase original data A.insert( A.end(), B.begin(), B.end() ); // add B; return A; // here A could be named AB }


Depende de si realmente necesita concatenar físicamente los dos vectores o si quiere dar la apariencia de concatenación del bien de la iteración. La función boost :: join

http://www.boost.org/doc/libs/1_43_0/libs/range/doc/html/range/reference/utilities/join.html

te dará esto

std::vector<int> v0; v0.push_back(1); v0.push_back(2); v0.push_back(3); std::vector<int> v1; v1.push_back(4); v1.push_back(5); v1.push_back(6); ... BOOST_FOREACH(const int & i, boost::join(v0, v1)){ cout << i << endl; }

debería darte

1 2 3 4 5 6

Nota boost :: join no copia los dos vectores en un nuevo contenedor sino que genera un par de iteradores (rango) que cubren el espacio de ambos contenedores. Habrá una sobrecarga de rendimiento, pero tal vez menos que copiar primero todos los datos a un nuevo contenedor.


Esto es precisamente lo que la función miembro std::vector::insert es para

std::vector<int> AB = A; AB.insert(AB.end(), B.begin(), B.end());


Si sus vectores están ordenados *, consulte set_union desde <algorithm>.

set_union(A.begin(), A.end(), B.begin(), B.end(), AB.begin());

Hay un ejemplo más completo en el enlace

* gracias rlbond


Todas las soluciones son correctas, pero me pareció más fácil simplemente escribir una función para implementar esto. Me gusta esto:

template <class T1, class T2> void ContainerInsert(T1 t1, T2 t2) { t1->insert(t1->end(), t2->begin(), t2->end()); }

De esta forma puede evitar la ubicación temporal de esta manera:

ContainerInsert(vec, GetSomeVector());


una variante más simple que no fue mencionada a chorro:

copy(A.begin(),A.end(),std::back_inserter(AB)); copy(B.begin(),B.end(),std::back_inserter(AB));

y usando el algoritmo de fusión:

#include <algorithm> #include <vector> #include <iterator> #include <iostream> #include <sstream> #include <string> template<template<typename, typename...> class Container, class T> std::string toString(const Container<T>& v) { std::stringstream ss; std::copy(v.begin(), v.end(), std::ostream_iterator<T>(ss, "")); return ss.str(); }; int main() { std::vector<int> A(10); std::vector<int> B(5); //zero filled std::vector<int> AB(15); std::for_each(A.begin(), A.end(), [](int& f)->void { f = rand() % 100; }); std::cout << "before merge: " << toString(A) << "/n"; std::cout << "before merge: " << toString(B) << "/n"; merge(B.begin(),B.end(), begin(A), end(A), AB.begin(), [](int&,int&)->bool {}); std::cout << "after merge: " << toString(AB) << "/n"; return 1; }


AB.reserve( A.size() + B.size() ); // preallocate memory AB.insert( AB.end(), A.begin(), A.end() ); AB.insert( AB.end(), B.begin(), B.end() );