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
How to Remove Straight Lines or Non-Curvical Lines in a Canny Image
Strange Behavior of Const_Cast
Initialize Base Class with No Default Constructor in Constructor of Derived Class
Why Does Int8_T and User Input via Cin Shows Strange Result
How to Do Static_Assert with MACros
Get a Reverse Iterator from a Forward Iterator Without Knowing the Value Type
Will Automatic Return Type Deduction Work for Main
C++: Initialization of Inherited Field
How Can Cstring Be Passed to Format String %S
Std::Vector Capacity After Copying
Why "Foo F(Bar());" Can Be a Declaration of a Function That Takes Type Bar and Returns Type Foo
Application Has Failed to Start Because Msvcp100D.Dll Was Not Found, Reinstalling App May Work
Ptr->Hello(); /* Versus */ (*Ptr).Hello();
Default Move Constructor in Visual Studio 2013 (Update 3)
How to Check If a File Has Been Opened by Another Application in C++
Possible Memory Leak Without a Virtual Destructor
How to Legally Reinterpret_Cast Between Layout-Compatible Standard-Layout Types