views:

71

answers:

3

hello stack overflow!

i want to do something like c# linq style :

SomeColection <SomeType> someColection;
someColection.Remove(something => something > 2);

and it'll remove all the things that are bigger then 2 (or any other boolean condition)...

using boost in the project...

+4  A: 

You don't need boost (unless your main focus is that inline anonymous function). Plain STL is fine.

#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>

int main () {
        std::vector<int> x (24);
        for (int i = 0; i < x.size(); ++ i)
                x[i] = i % 5;

        std::vector<int>::iterator
          new_end = std::remove_if(x.begin(), x.end(),
                                   std::bind2nd(std::greater<int>(), 2));
        x.erase(new_end, x.end());

        for (int i = 0; i < x.size(); ++ i)
                std::cout << x[i] << " ";

        return 0;
}

With boost you can replace the bind2nd stuff with

#include <boost/lambda/lambda.hpp>

...

    using boost::lambda::_1;
    std::vector<int>::iterator new_end = std::remove_if(x.begin(), x.end(), _1 > 2);
KennyTM
+1. I would just replace the output line with an `std::copy( x.begin(), x.end(), std::ostream_iterator<int>( std::cout, " " ) );` to hide the loop away... but that is just a matter of taste :)
David Rodríguez - dribeas
+3  A: 

First, you need a simple template wrapper:

template <class Container, class UnaryPredicate>
void erase_if(Container& container, UnaryPredicate pred)
{
  container.erase(
    std::remove_if(container.begin(), container.end(), pred),
    container.end()
  );
}

It's a well-known idiom, however it won't be possible with map or set as they maintain their own order.

Then, you can use Boost.Lambda to get the syntax you wish for writing the predicate itself.

using boost::lambda::_1;

SomeCollection<Type> someCollection;

erase_if(someCollection, _1 > 2);
Matthieu M.
for the lambda expression
Hellfrost
+3  A: 

C++0x (using lambdas):

container.erase( std::remove_if( container.begin(), container.end(), 
                                 []( int v ) { return v > 2; } ),
                 container.end() );

The reason for the erase combined with the remove_if is that STL algorithms apply to iterators, and not containers. They relocate the contents of the container, but they do not modify the container per-se.

C++03:

container.erase( std::remove_if( container.begin(), container.end(), 
                                 std::bind2nd( std::greater<int>(), 2 ) ),
                 container.end() );

This may seem a little simpler, but it is also less flexible, as there are only so many predicates already defined. For more complex operations you would have to write your own predicate functor.

David Rodríguez - dribeas
Loving the 0x lambdas
DanDan
can i do that in MS visual studio?
Hellfrost
@Hellfrost: If you are using VS2010 you can.
David Rodríguez - dribeas
VS 2008 still... but hopefully in the next couple of weeks we'll get 2010
Hellfrost