Std::Vector Removing Elements Which Fulfill Some Conditions

std::vector removing elements which fulfill some conditions

std::remove_if comes to the rescue!

99 would be replaced by UnaryPredicate that would filter your delays, which I am going to use a lambda function for.

And here's the example:

v.erase(std::remove_if(
v.begin(), v.end(),
[](const int& x) {
return x > 10; // put your condition here
}), v.end());

How to erase elements from a vector based on a specific condition in c++11

You want to erase-remove idiom, which is the standard way to remove elements from an STL container which support a condition. This code snippet will remove all vector elements for which predicate returns true:

vector.erase(std::remove_if(vector.begin(), vector.end(), predicate), vector.end());

A predicate for which checks if z < 0 is:

auto predicate = [](const vec3 &v) { return v.z < 0; }

Removing elements from C++ std::vector

bool IsEven (int i) 
{
return (i%2) == 0;
}

//...

std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.erase(std::remove_if(v.begin(),v.end(),IsEven), v.end());
//v now contains 1 and 3

How to delete all tuples in a vector with a certain condition?

Answer adopted from std::vector removing elements which fulfill some conditions. With the remove_if function template one could do,

things.erase(std::remove_if(
things.begin(), things.end(),
[](const thing& x) -> bool{
return get<1>(x) == 4; // put your condition here
}), things.end());

See an example at C++ Shell.

C++ Erase objects from vector based on member function

You can use std::mem_fn to adapt a pointer-to-member-function as a function object with an explicit parameter of the class.

std::vector<Destroyable> vec = /* some values */
auto last = std::remove_if(vec.begin(), vec.end(), std::mem_fn(&Destroyable::isDestroyed));
vec.erase(last, vec.end());

In C++20 you can reduce the boilerplate

std::erase_if(vec, std::mem_fn(&Destroyable::isDestroyed));

How to delete an element from a vector while looping over it?

The idiomatic way to remove all elements from an STL container which satisfy a given predicate is to use the remove-erase idiom. The idea is to move the predicate (that's the function which yields true or false for some element) into a given function, say pred and then:

static bool pred( const std::string &s ) {
// ...
}

std::vector<std::string> v;
v.erase( std::remove_if( v.begin(), v.end(), pred ), v.end() );

If you insist on using indices, you should not increment the index for every element, but only for those which didn't get removed:

std::vector<std::string>::size_type i = 0;
while ( i < v.size() ) {
if ( shouldBeRemoved( v[i] ) ) {
v.erase( v.begin() + i );
} else {
++i;
}
}

However, this is not only more code and less idiomatic (read: C++ programmers actually have to look at the code whereas the 'erase & remove' idiom immediately gives some idea what's going on), but also much less efficient because vectors store their elements in one contiguous block of memory, so erasing on positions other than the vector end also moves all the elements after the segment erased to their new positions.

How to remove elements from vector in the cycle in C++

For such a task it is better to use standard algorithm std::unique with a predicate and then to apply the member function erase to the returned iterator.

As for your code then it is invalid. You should not increase the index when an element is erased.

Here is a demonstrative program that shows how the algorithm std::unqiue can be used

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>

int main()
{
std::vector<double> v = { 1, 1.5, 3, 4.5, 5 };
const double delta = 1.0;

for ( const auto &x : v ) std::cout << x << ' ';
std::cout << std::endl;

v.erase(
std::unique( v.begin(), v.end(),
[&]( const auto &x, const auto &y )
{
return ::abs( x - y ) < delta;
} ),
v.end() );

for ( const auto &x : v ) std::cout << x << ' ';
std::cout << std::endl;

return 0;
}

Its output is

1 1.5 3 4.5 5 
1 3 4.5

Most efficient way of erasing/deleting multiple std::vector elements while retaining original order?

In <algorithm> there is a remove_if function which squeezes all values not removed to the front maintaining the order. This works if those 200 elements can be purely determined by the values, not index.

This is essentially the Erase-remove idiom you have linked to. remove_if is guaranteed to perform O(N) comparisons (and at most O(N) copyings), which would be more efficient than sorting (O(N log N)), although your last option doesn't actually require sorting if the indices are determined from values (just scan in the reversed direction while copying).

Nevertheless, using remove_if (if you can) is better than the other 2 options because the implementation has already been written for you, so there's less chance of logical error and conveys better what (not how) to do.



Related Topics



Leave a reply



Submit