2010-09-03 14 views
7

¿La biblioteca estándar de C++ y/o Boost tienen algo similar a la función filter que se encuentra en los lenguajes funcionales?"filtro" función de orden superior en C++

La función más cercana que pude encontrar fue std::remove_copy_if pero parece estar haciendo lo contrario de lo que quiero. ¿Tiene boost::lambda alguna función para obtener una versión negada de mi predicado (similar a not en Haskell)? Podría negar mi predicado y usarlo con std::remove_copy_if.

Tenga en cuenta que no estoy preguntando cómo escribir la función filter en C++; Solo estoy preguntando si la biblioteca estándar y/o Boost ya proporcionan esa función.

Gracias de antemano.

+0

¿Cómo es 'std :: remove_copy_if()' al contrario de lo que quieres? ¿Qué es lo opuesto a lo opuesto? Si solo quiere eliminar los elementos en su lugar, use eliminar/borrar idioma: 'container.erase (std :: remove_if (container.begin(), container.end(), pred()), container.end()); ' – wilx

+0

@wilx: Quiero que los elementos que satisfagan el predicado se retengan y otros se eliminen. – missingfaktor

Respuesta

6

Incluir <functional> para std::not1 y tratar cont.erase (std::remove_if (cont.begin(), cont.end(), std::not1 (pred())), cont.end());

+0

Exactamente lo que quería. ¡Gracias! :-) – missingfaktor

+0

Aah, espera. No quiero que la colección original sea mutada. Quiero una nueva copia modificada. – missingfaktor

+1

@Missing Faktor: luego quieres 'remove_copy_if' en lugar de' remove_if'. –

6

Hay un filtro equivalente en Boost.Range.
Aquí se muestra un ejemplo:

#include <vector> 
#include <boost/lambda/lambda.hpp> 
#include <boost/range/algorithm_ext/push_back.hpp> 
#include <boost/range/adaptor/filtered.hpp> 

using namespace boost::adaptors; 
using namespace boost::lambda; 

int main() 
{ 
    std::vector<int> v = {3, 2, 6, 10, 5, 2, 45, 3, 7, 66}; 
    std::vector<int> v2; 
    int dist = 5; 

    boost::push_back(v2, filter(v, _1 > dist)); 
    return 0; 
} 
+0

+1, esta es una buena solución también. – missingfaktor

1

encuentro un montón de tareas de estilo funcional puede ser resuelto mediante la combinación de boost.iterators. Para esto, tiene filter_iterator.

Say, que tiene un vector de números naturales, y una función que se desea aplicar a un par de iteradores, que sólo debe ver el vector filtrada, con sólo los números impares:

#include <algorithm> 
#include <vector> 
#include <iterator> 
#include <numeric> 
#include <iostream> 
#include <boost/iterator/filter_iterator.hpp> 
template<typename Iter> 
void do_stuff(Iter beg, Iter end) 
{ 
    typedef typename std::iterator_traits<Iter>::value_type value_t; 
    copy(beg, end, std::ostream_iterator<value_t>(std::cout, " ")); 
    std::cout << '\n'; 
} 
struct is_even { 
     bool operator()(unsigned int i) const { return i%2 == 0; } 
}; 
int main() 
{ 
     std::vector<unsigned int> v(10, 1); 
     std::partial_sum(v.begin(), v.end(), v.begin()); // poor man's std::iota() 

     // this will print all 10 numbers 
     do_stuff(v.begin(), v.end()); 
     // this will print just the evens 
     do_stuff(boost::make_filter_iterator<is_even>(v.begin(), v.end()), 
       boost::make_filter_iterator<is_even>(v.end(), v.end())); 

} 
1

Uso remove_if o remove_copy_if, con not1 (definido en <functional>) para invertir el predicado. Algo como esto:

#include <algorithm> 
#include <functional> 

template <class ForwardIterator, class Predicate> 
ForwardIterator filter(ForwardIterator first, ForwardIterator last, 
         Predicate pred) 
{ 
    return std::remove_if(first, last, std::not1(pred)); 
} 

template <class InputIterator, class OutputIterator, class Predicate> 
OutputIterator filter_copy(InputIterator first, InputIterator last, 
          OutputIterator result, Predicate pred) 
{ 
    return std::remove_copy_if(first, last, result, std::not1(pred)); 
} 
Cuestiones relacionadas