2010-11-19 10 views
15

Esiste un algoritmo STL/boost che verificherà se tutti gli elementi tra due iteratori corrispondono a un determinato valore? O in alternativa che un predicato restituisce true per tutti loro?Esiste un algoritmo STL/boost per verificare che tutti gli elementi in un contenitore corrispondano a un valore?

vale a dire una cosa del genere

template<class InputIterator, class T> 
InputIterator all_match (InputIterator first, InputIterator last, const T& value) 
{ 
    bool allMatch = true; 
    while(allMatch && first!=last) 
     allMatch = (value == *first++); 
    return allMatch; 
} 

O

template <class InputIterator, class Predicate> 
bool all_true (InputIterator first, InputIterator last, Predicate pred) 
{ 
    bool allTrue = true; 
    while (allTrue && first != last) 
     allTrue = pred(*first++); 
    return allTrue; 
} 

risposta

22

Se si può negare il predicato è possibile utilizzare std :: trovare/std :: find_if e vedere se restituisce l'elemento terminale della sequenza. In caso contrario, restituisce quello che corrisponde.

È possibile adattare una funzione con std :: not1 o std :: not_equal_to così facendo combinato con std :: find_if si può effettivamente farlo usando STL senza scrivere un ciclo.

bool allMatch = seq.end() == std::find_if(seq.begin(), seq.end(), 
    std::not_equal_to(val)); 
bool allPass = seq.end() == std::find_if(seq.begin(), seq.end(), 
    std::not1(pred)); 
+0

Che farà bene. Grazie. – GrahamS

+4

in realtà non penso che la sintassi 'not_equal_to()' sia giusta. Potrei fare qualcosa di sbagliato, ma ho dovuto usare 'bind2nd' con esso in questo modo:' std :: find_if (seq.begin(), seq.end(), std :: bind2nd (std :: not_equal_to () , val)) ' – GrahamS

2

Si potrebbe usare std: trovare ord std :: find_if per fare questo.

template <class T> 
struct pred { 
    T t_; 

    pred(const T& value) : t_(value) {} 

    bool operator()(const T &t) 
    { 
     return t != t_; 
    } 
}; 

if (e.cend() == std::find_if(c.cbegin(), c.cend(), pred<T>(value))) 
    print("all match value"); 
+0

Come ho capito, find e find_if individuano solo la prima corrispondenza in un contenitore. Voglio verificare che OGNI elemento tra gli iteratori sia un valore dato. – GrahamS

+0

La mia modifica mostra come dovrebbe funzionare? – frast

+0

Scusa, il mio predicato era scontato. L'ho corretto ora. – frast

2

È possibile utilizzare std::equal con il predicato. Qualcosa di simile:

using namespace std; 
using namespace boost::lambda; 

int main() 
{ 
    vector<int> a; 
    a.push_back(1); 
    a.push_back(1); 
    a.push_back(2); 
    a.push_back(2); 
    a.push_back(3); 
    bool allMatch = equal(a.begin(), a.begin() + 2, a.begin(), _1 == 1); 
    return 0; 
} 
18

C++ 0x introduce std::all_of.

+0

@avakar: Sezione 25.1 [algorithms.general] Introduce anche' std :: any_of' e 'std :: none_of' (e il famigerato' std :: copy_if'). –

+0

@avakar: non stiamo usando C++ 0x ma è utile sapere comunque, grazie. – GrahamS

+0

Questo è interessante. Mostra C++ 0x pone uno spostamento verso un'interfaccia più umana. – wilhelmtell

1

Spesso si può semplicemente contare:

template<class FwdIterator, class T> 
InputIterator all_match (FwdIterator first, FwdIterator last, const T& value) 
{ 
    return std::count(first, last, value) == std::distance(first, last); 
} 

inefficiente quando l'iteratore non è casuale, o quando restituisce false. Non funziona per gli iteratori di input.

+0

Inoltre non si ferma non appena trova una non corrispondenza, il che lo rende meno ideale per i contenitori molto grandi. – GrahamS

Problemi correlati