Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing by index from a C++ vector using remove_if

We can use remove_if in C++ to remove elements from a vector in linear time based on a predicate that operates on the elements.

bool condition(double d) {...}

vector<double> data = ...
std::remove_if (data.begin(), data.end(), condition);

What if my condition depends not on the values, but on the indices? In other words, if I wanted to remove all the odd-indexed elements, or some arbitrary index set, etc?

bool condition(int index) {//returns whether this index should be removed}

vector<double> data = ...
std::remove_if (data.begin(), data.end(), ???);
like image 638
donnyton Avatar asked Apr 17 '14 00:04

donnyton


People also ask

How do I remove a specific index from a vector?

vector::erase() erase() function is used to remove elements from a container from the specified position or range.

How do you remove values from a vector?

vector::clear() clear() removes all elements from vector and reducing it to size 0. erase() is used to remove specific elements from vector.

What does Remove_if return C++?

The remove_if() function returns an iterator that points to past the last element that is not removed.

How do you remove a random element from a vector?

The idea is to swap the last element and an element you want to remove and then pop_back() . If you need to remove the last elemtent - just pop_back() . The order of the vector will not be the same but you get a fast remove method.


2 Answers

You can use pointer arithmetic to find the index of a specific element that std::remove_if passes to the predicate:

std::remove_if(data.begin(), data.end(),
               [&data](const double& d) { return (&d - &*data.begin()) % 2); });

Note that remove_if passes the result of dereferencing an iterator, and that's guaranteed to be a reference per Table 106 - Iterator requirements in the Standard.

like image 162
Tony Delroy Avatar answered Oct 12 '22 12:10

Tony Delroy


I actually made an account only for this. Use awesomeyi answer. Is way cleaner.

int count = 0;
auto final = std::remove_if (data.begin(), data.end(), [&count](const double d) {
    return (count++) % 2;
});

The standard does say that the predicate is applied exactly last - first times. And remove_if works with ForwardIterators.

This implies that the predicate is applied only once in the same order they originally appear in the sequence.

Unless of course, the library is trolling you, by keeping internal copies of the ForwardIterator.

like image 31
jonas simple Avatar answered Oct 12 '22 13:10

jonas simple