2015-11-12 24 views
7

Ho una funzione:Keeping vettore di iteratori dei dati

void get_good_items(const std::vector<T>& data,std::vector<XXX>& good_items); 

Questa funzione dovrebbe controllare tutti i dati e trovare gli oggetti che soddisfa una condizione e tornare dove sono in good_items.

cosa è meglio invece di std::vector<XXX>?

  1. std::vector<size_t> che contiene tutti gli indici validi.
  2. std::vector<T*> che contengono un puntatore agli articoli.
  3. std::vector<std::vector<T>::iterator> che contiene iteratori per gli articoli.
  4. altro ??

EDIT:

Cosa farò con il good_items? Molte cose ... una di queste è cancellarle dal vettore e salvarle in altro luogo. forse qualcos'altro dopo

EDIT 2:

Uno dei più importante per me è come sarà l'accesso alle voci in data sarà veloce a seconda della struct di good_items?

EDIT 3:

Ho appena relized che il mio pensiero era sbagliato. Non è meglio mantenere puntatori grezzi (o intelligenti) come elementi del vettore in modo da poter mantenere i valori reali del vettore (che sono i puntatori) e non ho paura della copia pesante perché sono solo indicatori?

+0

Userete il risultato solo nella funzione di chiamata, o voi tentare di memorizzarlo in modo da poterlo riutilizzare (dopo che il vettore potrebbe essere già stato modificato)? Qualsiasi altro codice (eventualmente in un thread diverso) modificherà il vettore tra "get_good_items" e il tuo utilizzo del risultato? – CompuChip

+0

Per ora non preoccupiamoci del thread-safty –

+0

Se il vettore dati viene modificato (cancellando elementi da esso, spostandolo da un intervallo di memoria ad un altro ecc.) I riferimenti si interromperanno. In questo caso è possibile copiare gli elementi validi dai dati a good_items. Se il vettore di dati non sarà armeggiato, puoi facilmente memorizzare i puntatori (quindi 2 sarebbe la strada da percorrere poiché omho è più facile da gestire ed è più leggibile) agli elementi. – rbaleksandar

risposta

4

Se rimuovi gli elementi dal vettore originale, ognuno dei metodi che hai elencato sarà un problema.

Se si aggiungono elementi al vettore originale, il secondo e il terzo saranno problematici. Il primo non sarà un problema se si utilizza push_back per aggiungere elementi.

Tutti loro andranno bene se non si modifica il vettore originale.

Dato che, mi consiglia di utilizzare std::vector<size_t>.

2

Se si intende rimuovere gli elementi che soddisfano il predicato, l'idioma di cancellazione-rimozione è la soluzione più semplice.

Se si intende copiare tali elementi, quindi std::copy_if è la soluzione più semplice.

Se si intende finire con due partizioni del contenitore, vale a dire un contenitore ha i buoni e un altro i cattivi, quindi std::partition_copy è una buona scelta.

Per consentire generalmente l'iterazione di tali elementi, una soluzione efficiente sta restituendo un intervallo di tali iteratori che controlleranno il predicato durante l'iterazione. Non penso che esistano tali iteratori nella libreria standard, quindi dovrai implementarli tu stesso. Per fortuna hai già fatto questo per te: http://www.boost.org/doc/libs/release/libs/iterator/doc/filter_iterator.html

2

Vorrei andare con std::vector<size_t> o std::vector<T*> perché sono più facili da digitare. Altrimenti, quei tre vettori sono praticamente equivalenti, tutti identificano le posizioni degli elementi.

std::vector<size_t> può essere utilizzato per utilizzare un tipo più piccolo per gli indici se si conoscono i limiti.

Se ci si aspetta che ci siano molti elementi in questo vettore, si potrebbe considerare di utilizzare boost::dynamic_bitset invece di risparmiare memoria e aumentare l'utilizzo della cache della CPU. Un po 'per elemento, la posizione del bit è l'indice nel vettore originale.

+0

In che modo std :: vector identifica la posizione? ad esempio, posso conoscere l'indice dell'elemento nel vettore dal suo puntatore raw? –

+0

Sì, certo che può perché la contiguità del vettore. Fuori campo .. funzionerebbe per altri contenitori? –

+0

@HumamHelfawi Qualcosa mi dice che conosci la risposta alla tua stessa domanda. Questo è più simile a una struttura di dati incidentali, vedere https://youtu.be/sWgDk-o-6ZE per maggiori dettagli. –

0

Il problema si sta risolvendo, dalla mia comprensione, è l'intersezione di due set, e vorrei andare per la soluzione dalla libreria standard: std::set_intersection