Std::Remove_If - Lambda, Not Removing Anything from the Collection

std::remove_if - lambda, not removing anything from the collection

You need to call erase on the iterator returned from remove_if, It should look something like this:

auto new_end = std::remove_if(MyDisplayDevices.begin(), MyDisplayDevices.end(),
[](const DisplayDevice3d& device)
{ return device.Modes.size() == 0; });

MyDisplayDevices.erase(new_end, MyDisplayDevices.end());

Using std::remove_if with lambda predicate to delete multiple elements

Without changing your structures, the quickest fix is to invert the whole loop and check deletedPoints from inside the lambda instead.

Then, make deletedPoints a std::set<int> storing your unique IDs. Then it'll be relatively fast, because std::set<int>::find doesn't need to scan the entire container, though your final complexity will still not be quite linear-time.

std::vector<Point> points_;
std::set<int> deletedPointIds_;

/// Remove by id
auto removeIt = std::remove_if(points_.begin(), points_.end(),
[&](const TrailPoint2& point)
{ return deletedPointIds_.count(point.id_); });
points_.erase(removeIt, points_.end());
deletedPointIds_.clear();

That being said, whether the switch over to std::set will be actually faster depends on a few things; you lose memory locality and drop cache opportunities due to the way in which set's elements are stored.

An alternative might be to keep the vector (of IDs not points!), pre-sort it, then use std::binary_search to get the benefits of a quick search as well as the benefits of sequentially-stored data. However, performing this search may not be suitable for your application, depending on how much data you have and on how often you need to execute this algorithm.

You could also use a std::unordered_set<int> instead of a std::set; this has the same problems as a std::set but the hash-based lookup may be faster than a tree-based lookup. Again, this entirely depends on the size, form and distribution of your data.

Ultimately, the only way to know for sure, is to try a few things at simulated extents and measure it.

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

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());

c++ STL remove-if algorithm and erase algorithm issue.

When you call std::remove/remove_if, it moves elements which don't satisfy the condition to the front of the range. The values of any remaining elements (starting from the position of the returned iterator) are unspecified. Some people seem to think that it swaps the elements such that the ones which satisfy the condition are moved to the back. But the algorithm is not specified to do this. If that's the result you want, then the algorithm you are looking for is std::partition.

Boost phoenix or lambda library problem: removing elements from a std::vector

You need boost::labmda::bind to lambda-ify function calls, for example the length < 24 part becomes:

bind(&string::length, _1) < 24

EDIT

See "Head Geek"'s post for why set::find is tricky. He got it to resolve the correct set::find overload (so I copied that part), but he missed an essential boost::ref() -- which is why the comparison with end() always failed (the container was copied).

int main()
{
vector<string> strings = getstrings();
set<string> others = getothers();
set<string>::const_iterator (set<string>::*findFn)(const std::string&) const = &set<string>::find;
strings.erase(
remove_if(strings.begin(), strings.end(),
bind(&string::length, _1) < 24 &&
bind(findFn, boost::ref(others), _1) == others.end()
), strings.end());
copy(strings.begin(), strings.end(), ostream_iterator<string>(cout, ", "));
return 0;
}

How to emulate remove_unless

std::not1 presumes your function object will derive from std::unary_function, or at least provide the same interface, so it'll have typedefs for result_type and argument_type.

Since a lambda won't define those, you won't be able to use not1 on them.

The obvious choice would be to create something similar to not1 yourself, but using more modern techniques to detect/pass through the argument/result type from whatever it modifies.

If you really want to use not1, then the most sensible approach would be to do the comparison with std::less and std::bind to specify the value to which you're going to compare (i.e., it's basically a C++03 thing, so if you're going to use it, you write everything in the style of C++03).

C++ lambda remove elements from set of vectors

std::remove_if() cannot be used with a set.

The only way to remove values from a set is with its erase() method.

std::remove_if() removes values from a sequence by literally copying them, and returning the ending iterator value of the new sequence. You do call erase(), using the ending iterator value, but this is not enough.

std::remove_if() is meant to be used with sequence containers, like std::vector or std::list, where you can remove individual elements simply by copying over them. But this does not work with a std::set(), because std::remove_if() knows nothing about the set's erase() method, the only way to remove values from a set.

You will need to write your own code to iterate over the set, correctly, and remove the values that you want to remove.

Watch out for the most frequent pitfall: after removing an element from a set, the iterator you just removed is no longer valid.



Related Topics



Leave a reply



Submit