2010-09-03 45 views
7

C++標準庫和/或Boost是否具有類似於函數式語言中的filter函數?在C++中「過濾」高階函數

我能找到的最接近的函數是std::remove_copy_if,但它似乎與我想要的相反。 boost::lambda有任何函數來獲得我的謂詞的否定版本(類似於Haskell中的not)?我可以否定我的謂詞,然後使用std::remove_copy_if

請注意,我不問如何在C++中編寫filter函數;我只是問標準庫和/或Boost是否已經提供了這樣的功能。

在此先感謝。

+0

'std :: remove_copy_if()'與你想要的相反嗎?相反的是什麼? (container.begin(),container.end(),pred()),container.end()。如果你只想刪除元素,使用remove/erase idiom:container.erase(std :: remove_if );' – wilx 2010-09-03 12:49:34

+0

@wilx:我想要保留滿足謂詞的元素,並刪除其他元素。 – missingfaktor 2010-09-03 12:51:18

回答

6

包括<functional>std::not1,並嘗試cont.erase (std::remove_if (cont.begin(), cont.end(), std::not1 (pred())), cont.end());

+0

正是我想要的。謝謝! :-) – missingfaktor 2010-09-03 13:17:17

+0

啊,等等。我不希望原始集合發生變異。我想要一個新的修改後的副本。 – missingfaktor 2010-09-03 13:45:06

+1

@Missing Faktor:那麼你想'remove_copy_if'而不是'remove_if'。 – 2010-09-03 14:08:45

6

有一個等效於Boost.Range的過濾器。
下面是一個例子:

#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,這也是一個不錯的解決方案。 – missingfaktor 2010-09-03 13:17:56

1

我找了很多的功能性風格的任務,可以通過組合boost.iterators來解決。爲此,它有filter_iterator

說,你必須要應用到一對迭代器,它應該只看到濾波矢量自然數的向量和函數,只有奇數:

#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

使用remove_ifremove_copy_ifnot1(在<functional>中定義)來反轉謂詞。就像這樣:

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