2008-11-24 26 views
30

Soy un programador de C/Python en C++ trabajando con el STL por primera vez.C++ ampliar un vector con otro vector

En Python, se extiende una lista con otra lista utiliza la .extend método:

>>> v = [1, 2, 3] 
>>> v_prime = [4, 5, 6] 
>>> v.extend(v_prime) 
>>> print(v) 
[1, 2, 3, 4, 5, 6] 

Actualmente uso este enfoque algorítmico para extender vectores en C++:

v.resize(v.size() + v_prime.size()); 
copy(v_prime.begin(), v_prime.end(), v.rbegin()); 

Es esta la forma canónica de extendiendo vectores, o si hay una manera más simple que me falta?

+0

duplicado Posible de [Concatenación de dos std :: vectores] (http://stackoverflow.com/questions/201718/concatenating-two-stdvectors) –

Respuesta

45

De here

// reserve() is optional - just to improve performance 
v.reserve(v.size() + distance(v_prime.begin(),v_prime.end())); 
v.insert(v.end(),v_prime.begin(),v_prime.end()); 
+0

No creo que haya una especialización de vector :: insert para los iteradores de entrada de acceso aleatorio, por lo que si el rendimiento importa, reserve() primero. –

+9

Tanto VC++ 9.0 como GCC 4.3.2 determinan la categoría de iterador internamente, por lo que no necesita reservar. –

+12

Sé que esto tiene 8 años, pero ¿hay alguna razón por la que usaste 'distance()' en lugar de simplemente 'v_prime.size()'? – Holt

18
copy(v_prime.begin(), v_prime.end(), back_inserter(v)); 
+0

Creo que el espacio todavía tiene que ser de reserva() - d para mejorar el rendimiento –

+1

+1, ya que el interlocutor pidió "más simple", no "más rápido", por lo que reservar espacio (aunque vale la pena mencionarlo como una opción) es innecesario. –

+0

creo que la solución dmitry es más simple y más rápida. Voto a favor de este chico en el pasado :) –

1

que necesitaba dos variantes diferentes de la función extend en C++ 14, donde uno de los admitidos semántica de movimiento para cada elemento del vector que se anexan.

vec es su v, y ext es su v_prime.

/** 
* Extend a vector with elements, without destroying source one. 
*/ 
template<typename T> 
void vector_extend(std::vector<T> &vec, const std::vector<T> &ext) { 
    vec.reserve(vec.size() + ext.size()); 
    vec.insert(std::end(vec), std::begin(ext), std::end(ext)); 
} 

/** 
* Extend a vector with elements with move semantics. 
*/ 
template<typename T> 
void vector_extend(std::vector<T> &vec, std::vector<T> &&ext) { 
    if (vec.empty()) { 
     vec = std::move(ext); 
    } 
    else { 
     vec.reserve(vec.size() + ext.size()); 
     std::move(std::begin(ext), std::end(ext), std::back_inserter(vec)); 
     ext.clear(); 
    } 
} 
3

Existen varias formas de lograr su objetivo.

std :: vector :: insertar

El vector se puede extender mediante la inserción de nuevos elementos antes de que el elemento en la posición especificada, aumentando efectivamente el tamaño del contenedor por el número de elementos insertados. Puede seguir uno de los siguientes enfoques. La segunda versión usa C++ 11 y se puede considerar como una respuesta más genérica, ya que b también podría ser una matriz.

a.insert(a.end(), b.begin(), b.end()); 
a.insert(std::end(a), std::begin(b), std::end(b)); 

Algunas veces en uso es una buena práctica usar la función de reserva antes de usar std :: vector :: insert. std :: vector :: reserve función aumenta la capacidad del contenedor a un valor que es mayor o igual a new_cap. Si new_cap es mayor que la capacidad actual(), se asigna nuevo almacenamiento, de lo contrario, el método no hace nada.

a.reserve(a.size() + distance(b.begin(), b.end())); 

No se requiere el uso de la función de reserva, pero puede ser aconsejable. Y es mejor utilizar la reserva si está insertando repetidamente en un vector para el que conoce el tamaño final, y ese tamaño es grande. De lo contrario, es mejor dejar que el STL haga crecer su vector según sea necesario.

std :: copia

std :: copia es la segunda opción que se puede considerar para lograr su objetivo. Esta función copia los elementos en el rango (primero, último) en el rango que comienza en el resultado.

std::copy (b.begin(), b.end(), std::back_inserter(a)); 

Sin embargo el uso de std :: copia es más lento que el uso de std :: vector :: insert(), porque std :: copy() no puede reservar espacio suficiente antes de mano (no lo hace tener acceso al propio vector, solo a un iterador que tiene), mientras que std :: vector :: insert(), siendo una función miembro, puede. Debido a que std :: copy es más lento que usar std :: vector :: insert. La mayoría de las personas sobre el uso estándar copia sin conocer este escenario.

impulso :: push_back

La tercera opción que se puede considerar es el uso de push_back función de impulso.

boost::push_back(a, b); 
1

Usando std::vector::insert;

A.reserve(A.size() + B.size()); 
A.insert(A.end(), B.begin(), B.end()); 

reserve() es opcional, pero el uso que ayuda a mejorar el rendimiento.


generador de código Convienent para guardar segundos preciosos:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css"><script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/js/materialize.min.js"></script><script src="https://cdn.jsdelivr.net/clipboard.js/1.6.0/clipboard.min.js"></script><script>function generateCode(){codeTemplate="{0}.reserve({0}.size() + {1}.size()); \n{0}.insert({0}.end(), {1}.begin(), {1}.end());",first=document.getElementById("1").value,second=document.getElementById("2").value,""==first&&(first="A"),""==second&&(second="B"),document.getElementById("c").innerHTML=String.format(codeTemplate,first,second)}String.format||(String.format=function(a){var b=Array.prototype.slice.call(arguments,1);return a.replace(/{(\d+)}/g,function(a,c){return"undefined"!=typeof b[c]?b[c]:a})});</script><div class="A" style="margin:3% 10% 1% 10%;"><label for="1">First vector name:</label><input id="1"/><br/><label for="1">Second vector name:</label><input id="2"/><div class="D"><a class="waves-effect waves-light btn red col" onclick="generateCode();" style="margin:0 0 4% 0;">Generate Code</a></div><textarea id="c" onclick="this.select()" style="border:none;height:auto;overflow: hidden;font-family:Consolas,Monaco;">A.reserve(A.size() + B.size());&#13;&#10;A.insert(A.end(), B.begin(), B.end());</textarea></div>