Patryk
Patryk

Reputation: 24092

Iterating over std::vector with lambda does not want to remove with remove_if

I have a small problem with lambda expression while using remove_if on std::vector

I have a following piece of code :

    std::remove_if( openList.begin(), openList.end(), 
        [&](BoardNode& i){
            std::cout<< i.getCoordinates() << std::endl;
            std::cout<< currentNode.getCoordinates() << std::endl;
            return i.getCoordinates() == currentNode.getCoordinates(); }
        );

There is no compiler error with this, but the elements which return true from the above statement won't be removed from the vector;

I get printed on the screen e.g.

[5,5]
[5,5]

but the openList remains as it was.

Upvotes: 2

Views: 2926

Answers (3)

Mike Seymour
Mike Seymour

Reputation: 254501

std::remove_if doesn't erase anything from the vector, since it doesn't have access to it. Instead, it moves the elements you want to keep to the start of the range, leaving the remaining elements in a valid but unspecified state, and returns the new end.

You can use the "erase-remove" idiom to actually erase them from the vector:

openList.erase(
    std::remove_if( 
        openList.begin(), 
        openList.end(), 
        [&](BoardNode& i){return i.getCoordinates() == currentNode.getCoordinates();}),
    openList.end());

Upvotes: 10

hate-engine
hate-engine

Reputation: 2350

Removing is done by shifting the elements in the range in such a way that elements to be erased are overwritten. The elements between the old and the new ends of the range have unspecified values. An iterator to the new end of the range is returned. Relative order of the elements that remain is preserved.

http://en.cppreference.com/w/cpp/algorithm/remove

Also, check the example on that link.

Upvotes: 0

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361522

I think you intend to remove items from the vector. But what you do, would not really remove the items from the vector, which makes you think that the lambda doesn't work. You need to use erase() member function in conjunction with std::remove.

In other words, you have to use erase-remove idiom as:

v.erase(std::remove_if(v.begin(), v.end(), your-lambda-goes-here), v.end());

Upvotes: 3

Related Questions