Supongamos que tengo un std::vector
(llamémoslo myVec
) de tamaño N
. ¿Cuál es la forma más simple de construir un nuevo vector que consiste en una copia de los elementos X a Y, donde 0 <= X <= Y <= N-1? Por ejemplo, a myVec [100000]
través myVec [100999]
de un vector de tamaño 150000
.
Si esto no se puede hacer de manera eficiente con un vector, ¿hay otro tipo de datos STL que debería usar en su lugar?
Respuestas:
Es una operación O (N) para construir el nuevo vector, pero en realidad no hay una mejor manera.
fuente
O(Y-X)
, o diríamosO(Z) where Z=Y-X
.vector<T> newVec(myVec.begin() + 100000, myVec.begin() + 101000);
?Solo usa el constructor de vectores.
fuente
operator[]
devuelve una referencia. Es solo en el punto donde lee o escribe la referencia que se convertiría en una violación de acceso. Como no hacemos ninguno de los dos, sino que obtenemos la dirección, no hemos invocado a UB.std::vector<T>(input_iterator, input_iterator)
, en su casofoo = std::vector<T>(myVec.begin () + 100000, myVec.begin () + 150000);
, vea por ejemplo aquífuente
En estos días, usamos
span
s! Entonces escribirías:para obtener un lapso de 1000 elementos del mismo tipo que
myvec
's. O una forma más concisa:(pero esto no me gusta tanto, ya que el significado de cada argumento numérico no está del todo claro; y empeora si la longitud y start_pos son del mismo orden de magnitud).
De todos modos, recuerde que esto no es una copia, es solo una vista de los datos en el vector, así que tenga cuidado. Si desea una copia real, puede hacer:
Notas:
gsl
significa Biblioteca de soporte de guías. Para más información sobregsl
, consulte: http://www.modernescpp.com/index.php/c-core-guideline-the-guidelines-support-library .gsl
, consulte: https://github.com/Microsoft/GSLspan
. Lo usaríasstd::span
y en#include <span>
lugar de#include <gsl/span>
.std::vector
tiene miles de millones de constructores, es muy fácil caer en uno que no pretendías usar, así que ten cuidado.fuente
cbegin
ycend
solo por el principio;)std::cbegin
etc incluso.Si no se van a modificar ambos (no se deben agregar / eliminar elementos; modificar los existentes está bien siempre que preste atención a los problemas de subprocesamiento), simplemente puede pasar
data.begin() + 100000
ydata.begin() + 101000
, y pretender que son elbegin()
yend()
de un vector más pequeño.O, dado que se garantiza que el almacenamiento vectorial sea contiguo, simplemente puede pasar una matriz de 1000 elementos:
Ambas técnicas toman tiempo constante, pero requieren que la longitud de los datos no aumente, lo que desencadena una reasignación.
fuente
Esta discusión es bastante antigua, pero la más simple aún no se menciona, con la inicialización de la lista :
Requiere c ++ 11 o superior.
Ejemplo de uso:
Resultado:
fuente
No mencionó qué tipo
std::vector<...> myVec
es, pero si es un tipo simple o estructura / clase que no incluye punteros, y desea la mejor eficiencia, puede hacer una copia de memoria directa (que creo que será más rápido que el otras respuestas proporcionadas). Aquí hay un ejemplo general destd::vector<type> myVec
dóndetype
en este caso esint
:fuente
std::vector(myVec.begin () + 100000, myVec.begin () + 150000);
, ¿la versión más larga de este producto no produciría exactamente el mismo ensamblaje?std::vector<>(iter, iter)
paramemmove()
, en su caso (si constructor es trivial, para una definición adecuada de trivial).memcpy
. Haga unstd::copy
o un constructor que acepte un rango (dos iteradores), y el compilador y el std.library conspirarán para llamarmemcpy
cuando sea apropiado.Podrías usar
insert
fuente
Puede usar la copia STL con rendimiento O (M) cuando M es el tamaño del subvector.
fuente
newvec.reserve(10100 - 10000);
. Definitivamente es una opción y técnicamente funcionará. Pero de los dos, ¿qué vas a recomendar?La única forma de proyectar una colección que no es tiempo lineal es hacerlo perezosamente, donde el "vector" resultante es en realidad un subtipo que delega en la colección original. Por ejemplo, el
List#subseq
método de Scala crea una subsecuencia en tiempo constante. Sin embargo, esto solo funciona si la colección es inmutable y si el idioma subyacente tiene una recolección de basura.fuente
Publicar esto tarde solo para otros ... Apuesto a que el primer codificador ya ha terminado. Para los tipos de datos simples, no se necesita copia, simplemente vuelva a los viejos métodos de código C.
Luego pase el puntero p y un len a cualquier cosa que necesite un subvector.
notelen debe ser !!
len < myVec.size()-start
fuente
Quizás el array_view / span en la biblioteca GSL es una buena opción.
Aquí también hay una implementación de archivo único: array_view .
fuente
Copie elementos de un vector a otro fácilmente
En este ejemplo, estoy usando un vector de pares para que sea fácil de entender
`
'
Como puede ver, puede copiar fácilmente elementos de un vector a otro, si desea copiar elementos del índice 10 al 16, por ejemplo, usaríamos
y si quieres elementos del índice 10 a algún índice desde el final, entonces en ese caso
Espero que esto ayude, solo recuerda en el último caso
v.end()-5 > v.begin()+10
fuente
Otra opción más: útil, por ejemplo, cuando se mueve entre ay
thrust::device_vector
athrust::host_vector
, donde no se puede usar el constructor.También debe ser complejidad O (N)
Puedes combinar esto con el código de respuesta superior
fuente