c++ - Using std::remove_if with lambda predicate to delete multiple elements -
what fastest , efficient way of using std::remove_if lambda predicate delete multiple elements @ same time? @ moment have point struct position , unique id. inside update loop fill points vector , add points deleted @ end of update loop. @ moment have call remove_if inside loop remove deleted points points vector. example if add 10 points per frame , after loop points check if point outside screen bounds, if added deletedpoints_.
struct point { /// position. vector3 position_; /// unique id per point int id_; } /// current max id int maxid_; /// points std::vector<point> points_; /// deleted points std::vector<point> deletedpoints_; //updates 60fps void app::update() { /// add 10 points per frame (int = 0; < 10; ++i) { point newpoint; /// add position newpoint.position_ = worldposition; /// add id starts 1 maxid_ += 1; startpoint.id_ = maxid_; /// add new point in points points_.push(newpoint); } /// if points outside of screen bounds add them deletedpoints_ if (points_.size() > 0) { (int = 0; < points_.size(); ++i) { /// bounds vector2 min = vector2(0.00,0.00); vector2 max = vector2(1.00,1.00); /// check bounds if(points_[i].x < min.x || points_[i].y < min.y || points_[i].x > max.x || points_[i].y > max.y) { deletedpoints_.push(points_[i]); } } /// loop deleted points (int = 0; < deletedpoints_.size(); ++i) { int id = deletedpoints_[i].id_; /// remove id auto removeit = std::remove_if(points_.begin(), points_.end(), [id](const trailpoint2& point) { return point.id_ == id; }); points_.erase(removeit, points_.end()); } } }
without changing structures, quickest fix invert whole loop , check deletedpoints
inside lambda instead.
then, make deletedpoints
std::set<int>
storing unique ids. it'll relatively fast, because std::set<int>::find
doesn't need scan entire container, though final complexity still not quite linear-time.
std::vector<point> points_; std::set<int> deletedpointids_; /// remove 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 switch on std::set
actually faster depends on few things; lose memory locality , drop cache opportunities due way in set
's elements stored.
an alternative might keep vector (of ids not points!), pre-sort it, use std::binary_search
benefits of quick search benefits of sequentially-stored data. however, performing search may not suitable application, depending on how data have , on how need execute algorithm.
you use std::unordered_set<int>
instead of std::set
; has same problems std::set
hash-based lookup may faster tree-based lookup. again, entirely depends on size, form , distribution of data.
ultimately, way know sure, try few things @ simulated extents , measure it.
Comments
Post a Comment