2011-12-09 10 views
5

indica che ho uno vector di pair<int,int>. Ora voglio estrarre il pair.first e il pair.second come vettori indipendenti. Posso scorrere il vettore e farlo ma c'è un modo migliore/più veloce?Il modo più veloce per convertire da vettore di coppie a due vettori indipendenti in C++

+0

Non vedo alcun modo di renderlo più veloce del loop su tutti gli elementi nel vettore. Tuttavia, non devi fare il loop, usa qualcosa come ['std :: for_each'] (http://en.cppreference.com/w/cpp/algorithm/for_each). –

+0

Sei sicuro di aver bisogno di copiare i valori in nuovi vettori? Forse potresti usare [transform_iterators] (http://www.boost.org/doc/libs/release/libs/iterator/doc/transform_iterator.html) per iterare semplicemente sul vettore originale mentre ottieni gli elementi di coppia, senza copiarli altrove. –

+0

si. ma non volevo usare boost. Ad ogni modo, tutti hanno dato la risposta corretta, quindi accetterò la risposta con i migliori "dettagli". – Neal

risposta

11

in C++ 11, se non avete bisogno di più il vecchio vettore, si potrebbe forse ottenere un po 'di efficienza in più da semantica move:

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)); 
} 

Oltre a questo, non si può certo fare meglio di un ciclo. Dovrai toccare ogni elemento almeno una volta, quindi è più efficiente che mai.

Si noti che lo spostamento può solo fare la differenza se i tipi di elementi stessi hanno semantica di movimento che è meglio della copia. Questo non è il caso di int s o di qualsiasi POD. Ma non può fare male scrivere il tuo codice genericamente in modo da poterlo sfruttare in situazioni future.

Se la copia/spostamento è un problema, tuttavia, è necessario considerare se un adattatore vista per il vettore originale potrebbe essere un approccio migliore.

+1

Whoa, non ho mai saputo di "make_move_iterator', +1 –

+0

@SethCarnegie: In realtà dubito che sia necessario qui; L'ho appena messo per divertimento (lo 'std :: move' dovrebbe già fare il trucco). L'iteratore di spostamento è molto utile per gli algoritmi, però. Viene pre-incartato in ['algorithm/std :: move'] (http://en.cppreference.com/w/cpp/algorithm/move), che è la versione mobile di' std :: copy'. –

+0

@KerrekSB: E quale sarebbe l'* extra efficiency * proveniente? Non penso che questo sarà più efficiente del più semplice anello idiomatico - il che è anche più facile da ragionare. –

3

No, non c'è. L'unica cosa di cui preoccuparsi è usare reserve sui due vettori risultanti per evitare riallocazioni non necessarie.

1

Devi comunque ripetere sul vettore, quindi in termini di complessità, questo è il massimo che puoi ottenere.

2

Non è possibile evitare l'iterazione. Per quanto riguarda la soluzione più veloce, dipende da cosa è nella coppia e dall'attuazione effettiva. In base a questi, potrebbe essere meglio creare i vettori di destinazione con la dimensione corretta e assegnarli a ; o per crearli vuoti e utilizzare reserve e quindi push_back. Si potrebbe anche voler confrontare l'indicizzazione con gli iteratori; se si utilizzano vettori di dimensioni preimpostate, l'utilizzo di una sola variabile di controllo anziché di tre potrebbe essere un miglioramento. (Con g ++, l'ultima volta ho misurato, creando vettori di dimensioni corrette e assegnazione era più veloce rispetto all'utilizzo reserve e push_back, almeno per double. Nonostante il fatto che significava loop due volte internamente e inizializzazione dei valori di 0.0.)

si potrebbe anche voler provare a creare oggetti funzionali per estrarre i primo e il secondo elemento della coppia (supponendo non si dispone già di loro ), e utilizzare due chiamate per transform. Di nuovo, con un vettore predimensionato o usando un inseritore posteriore come obiettivo. A parte, I non si aspettava che questo fornisse prestazioni migliori, ma non si sa mai.

Problemi correlati