2011-12-09 16 views
5

digamos que tengo un vector de pair<int,int>. Ahora quiero extraer pair.first y pair.second como vectores independientes. Puedo iterar sobre el vector y hacer eso, pero ¿hay una manera mejor/más rápida?La forma más rápida de convertir del vector de pares a dos vectores independientes en C++

+0

No veo ninguna forma de hacerlo más rápido que recorrer todos los elementos del vector. Sin embargo, usted no tiene que hacer el bucle, use algo como ['std :: for_each'] (http://en.cppreference.com/w/cpp/algorithm/for_each). –

+0

¿Estás seguro de que necesitas copiar los valores en nuevos vectores? Quizás podría usar [transform_iterators] (http://www.boost.org/doc/libs/release/libs/iterator/doc/transform_iterator.html) para simplemente iterar en el vector original mientras obtiene los elementos del par, sin copiarlos en otra parte. –

+0

sí. pero no quería usar boost De todos modos, todos han dado la respuesta correcta, así que aceptaré la respuesta con los mejores "detalles". – Neal

Respuesta

11

en C++ 11, si usted no necesita el vector viejo ya, tal vez podría conseguir un poco de eficacia adicional de la semántica movimiento:

for (auto it = std::make_move_iterator(v.begin()), 
     end = std::make_move_iterator(v.end()); it != end; ++it) 
{ 
    v1.push_back(std::move(it->first)); 
    v2.push_back(std::move(it->second)); 
} 

Aparte de eso, que sin duda no puede hacer mejor que un bucle Tendrá que tocar cada elemento al menos una vez, por lo que es lo más eficiente posible.

Tenga en cuenta que moverse solo puede hacer una diferencia si los tipos de elementos tienen una semántica de movimiento que es mejor que copiar. Este no es el caso para int s, o cualquier POD. Pero no tiene sentido escribir su código genéricamente para que pueda aprovechar esto en situaciones futuras.

Si copiar o mover es un problema, debe considerar si algún adaptador de vista para su vector original podría ser un mejor enfoque.

+1

Whoa, nunca supo sobre 'make_move_iterator', +1 –

+0

@SethCarnegie: En realidad, dudo que sea necesario aquí; Simplemente lo puse por diversión (el 'std :: move' ya debería hacer el truco). Sin embargo, el iterador de movimiento es muy útil para los algoritmos. Viene pre-envuelto en ['algorithm/std :: move'] (http://en.cppreference.com/w/cpp/algorithm/move), que es la versión móvil de' std :: copy'. –

+0

@KerrekSB: ¿Y de qué vendría la * eficiencia extra *? No creo que esto vaya a ser más eficiente que el loop simple más idiomático, que también es más fácil de razonar. –

3

No, no hay. Lo que hay que tener en cuenta es usar reserve en los dos vectores resultantes para evitar reasignaciones innecesarias.

1

Tiene que iterar sobre el vector de todos modos, por lo que en términos de Complejidad, esto es lo mejor que puede obtener.

2

No podrá evitar la iteración. En cuanto a la solución más rápida, depende de lo que hay en el par y de la implementación real. Dependiendo de esto, puede ser mejor crear los vectores de destino con el tamaño correcto y asignarlos; o para crearlos vacíos, y use reserve y luego push_back. También es posible que desee comparar la indexación con el uso de iteradores; Si usa vectores de tamaño preestablecido, usar una sola variable de control en lugar de tres podría ser una mejora. (Con g ++, la última vez Medí, la creación de vectores de la talla correcta y asignación era más rápido que el uso de reserve y push_back, al menos para double. A pesar del hecho que significaba bucle dos veces internamente, y inicializar los valores de 0.0.)

también puede ser que desee para tratar de crear objetos funcionales para extraer los primer y segundo elementos del par (suponiendo que no los tiene ya), y el uso de dos llamadas a transform. De nuevo, ya sea con un vector predimensionado o usando un insertador posterior como objetivo. De la mano, I no esperaría que esto proporcionara un mejor rendimiento, pero nunca se sabe.

Cuestiones relacionadas