2010-09-03 25 views
7

La libreria standard C++ e/o Boost hanno qualcosa di simile alla funzione filter trovata in lingue funzionali?"filtro" funzione di ordine superiore in C++

La funzione più vicina che ho trovato era std::remove_copy_if ma sembra che stia facendo l'opposto di quello che voglio. boost::lambda ha qualche funzione per ottenere una versione negata del mio predicato (simile a not in Haskell)? Potrei negare il mio predicato e usarlo con std::remove_copy_if quindi.

Si noti che non sto chiedendo come scrivere la funzione filter in C++; Sto solo chiedendo se la libreria standard e/o Boost già forniscono tale funzione.

Grazie in anticipo.

+0

Come è 'std :: remove_copy_if()' opposto di quello che vuoi? Qual è l'opposto del contrario? Se si desidera rimuovere solo elementi in posizione, utilizzare remove/cancella linguaggio: 'container.erase (std :: remove_if (container.begin(), container.end(), pred()), container.end()); – wilx

+0

@wilx: voglio che gli elementi che soddisfano il predicato siano mantenuti e altri rimossi. – missingfaktor

risposta

6

Includere <functional> per std::not1 e cercare cont.erase (std::remove_if (cont.begin(), cont.end(), std::not1 (pred())), cont.end());

+0

Esattamente quello che volevo. Grazie! :-) – missingfaktor

+0

Aah, aspetta. Non voglio che la collezione originale venga modificata. Voglio una nuova copia modificata. – missingfaktor

+1

@Missing Faktor: allora vuoi 'remove_copy_if' invece di' remove_if'. –

6

C'è un equivalente del filtro in Boost.Range.
Ecco un esempio:

#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, questa è una bella soluzione pure. – missingfaktor

1

trovo un sacco di compiti funzionali in stile può essere risolto mediante la combinazione di boost.iterators. Per questo, ha filter_iterator.

Dite, avete un vettore di numeri naturali, e una funzione che si desidera applicare a una coppia di iteratori, che dovrebbe vedere solo il vettore filtrato, con solo i numeri dispari:

#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

Usa remove_if o remove_copy_if, con not1 (definito in <functional>) per invertire il predicato. Qualcosa del genere:

#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)); 
} 
Problemi correlati