2012-10-20 3 views
5

Vorrei sapere come posso trovare le posizioni dell'indice degli elementi che verificano una determinata condizione (ad esempio maggiore di). Ad esempio se ho un vettore di valori intOttieni tutte le posizioni degli elementi nel vettore STL maggiori di un valore

vector<int> V; 

V contiene i valori 3 2 5 8 2 1 10 4 7

e voglio ottenere tutte le posizioni di indice di elementi che sono maggiori di 5. so std::find_if ma secondo la documentazione, trova solo il primo elemento che soddisfa una condizione.

+2

È possibile utilizzare 'std :: find_if' in un ciclo, la memorizzazione di posizioni, come si va. – chris

+1

usalo ripetutamente, iniziando non dall'inizio ma da dove hai appena trovato. –

+0

@oldrinb In realtà ho bisogno di ottenere le posizioni perché poi devo ottenere elementi da un altro vettore nelle stesse posizioni. – saloua

risposta

8

Loop std::find_if, a partire da dove si è fermato l'ultima volta.

campione (see it work):

std::vector<size_t> results; 

auto it = std::find_if(std::begin(v), std::end(v), [](int i){return i > 5;}); 
while (it != std::end(v)) { 
    results.emplace_back(std::distance(std::begin(v), it)); 
    it = std::find_if(std::next(it), std::end(v), [](int i){return i > 5;}); 
} 

In primo luogo abbiamo istituito l'iteratore con il primo risultato. Se non viene trovato, il ciclo while non viene mai eseguito. In caso contrario, la posizione dell'indice viene memorizzata (std::distance è fondamentalmente un più generico it - std::begin(v)) e la ricerca continua in avanti.

+0

+1 per 'std :: next' –

8

Penso userei std::copy_if:

std::vector<int> x{3, 2, 5, 8, 2, 1, 10, 4, 7}; 
std::vector<size_t> y(x.size()); 

std::iota(y.begin(), y.end(), 0); 
std::copy_if(y.begin(), y.end(), 
      std::ostream_iterator<size_t>(std::cout, " "), 
      [=](size_t i) { return x[i] > 5; }); 

Per me, questo dà 3 6 8, gli indici di 8, 10 e 7 in x - esattamente quello che vogliamo.

Se sei bloccato con un C++ 98/03 compilatore/biblioteca, userete std::remove_copy_if invece (e invertire il senso del confronto). In questo caso, ovviamente, non sarai in grado di utilizzare una lambda per il confronto.

+0

Mi piace. Pensare bene. – chris

+2

+1 per 'std :: iota' –

1

Solo per divertimento, transform_if algoritmo:

#include <vector> 
#include <iterator> 
#include <algorithm> 
#include <iostream> 

template<typename InputIterator, typename OutputIterator, 
    typename UnaryPredicate, typename UnaryFunction> 
OutputIterator 
transform_if (InputIterator first, InputIterator last, 
    OutputIterator result, UnaryPredicate pred, 
    UnaryFunction func) 
{ 
    for (; first != last; ++first, ++result) 
     if (pred(*first)) 
      *result = func(*first); 
    return result; 
} 

int main() 
{ 
    std::vector<int> x {3, 2, 5, 8, 2, 1, 10, 4, 7}; 
    std::vector<size_t> indices; 

    size_t index = 0; 
    transform_if(x.begin(), x.end(), std::back_inserter(indices), 
     [&](int i){ return ++index, i > 5; }, 
     [&](int){ return index-1; }); 

    std::copy(indices.begin(), indices.end(), 
       std::ostream_iterator<size_t>(std::cout, " ")); 
} 

uscita: 3 6 8