2010-11-19 13 views
15

¿Hay un algoritmo STL/boost que verificará si todos los elementos entre dos iteradores coinciden con un valor dado? ¿O alternativamente que un predicado devuelve true para todos ellos?¿Hay un algoritmo STL/boost para verificar que todos los elementos en un contenedor coinciden con un valor?

es decir, algo así como

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

Respuesta

22

Si se puede negar el predicado puede utilizar std :: find/std :: find_if y ver si se devuelve el elemento final de la secuencia. Si no, entonces devuelve el que no coincide.

Puede adaptar una función con std :: not1 o std :: not_equal_to haciendo esto combinado con std :: find_if puede hacerlo usando STL sin escribir un bucle.

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

Eso hará muy bien. Gracias. – GrahamS

+4

en realidad, no creo que la sintaxis 'not_equal_to()' sea correcta. Puedo estar haciendo algo mal, pero tuve que usar 'bind2nd' con esto así:' std :: find_if (seq.begin(), seq.end(), std :: bind2nd (std :: not_equal_to () , val)) ' – GrahamS

2

Usted podría utilizar std: encontrar ord std :: find_if para hacer esto.

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

Según tengo entendido, busque y encuentre_si solo encuentra la primera coincidencia en un contenedor. Quiero verificar que CADA elemento entre los iteradores sea un valor dado. – GrahamS

+0

¿Mi edición muestra cómo debería funcionar? – frast

+0

Lo siento, mi predicado era penoso. Lo corregí ahora. – frast

2

Puede utilizar std::equal con el predicado. Algo como:

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 presenta std::all_of.

+0

@avakar: Section 25.1 [algorithms.general] También introduce' std :: any_of' y 'std :: none_of' (y el infame' std :: copy_if'). –

+0

@avakar: no estamos usando C++ 0x, pero eso es útil saber de todos modos, gracias. – GrahamS

+0

Esto es interesante. Muestra que C++ 0x plantea un cambio hacia una interfaz más humana. – wilhelmtell

1

A menudo se puede contar sólo ellos:

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

ineficiente cuando el iterador no es al azar, o cuando se devuelve falso. No funciona para los iteradores de entrada.

+0

Además, no se detiene tan pronto como detecta una falta de coincidencia, lo que lo hace menos ideal para contenedores muy grandes. – GrahamS

Cuestiones relacionadas