-4

I have PointCloud.h where it gives points. I wrote something like this on my header file:

void RadiusOutlierFilter::filter(PointCloud& pc) {
    std::remove_if(pc.points(), pc.points() + pc.pointNumber(), [](const Point& p)
    {
        return(p < 0 && p>25);
    });
}

I wrote this without knowing what remove_if() does. I believe with this I remove the points under 0 and greater than 25, is it correct? How can I return the numbers between 0-25? If you can fix the code I would be very grateful, I'm pretty desperate at this point because I couldn't figured it out and it stresses me.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
filofil
  • 1
  • 1
  • 4
    If you use `remove_if()` without reading and understanding what it actually does, you will get very confused. – Fred Larson Dec 11 '19 at 20:49
  • 4
    How can a `Point` be both `< 0` and `> 25` at the same time? I think your statement will always evaluate as false, so will not remove anything. You likely meant to use `||` instead of `&&`. Also note that `remove_if()` doesn't actually remove anything, it just moves the "removed" elements to the end of the specified range, you have to then "erase" those elements to actually remove them from the container – Remy Lebeau Dec 11 '19 at 20:50

1 Answers1

1

std::remove_if() is a bit deceiving, because it doesn't actually remove anything. Rather, it moves all the values not meeting the removal criteria toward the beginning of the container, overwriting the ones that do meet the removal criteria. It returns an iterator pointing at the first "removed" entry. But the entries from that point on are not necessarily the removed values; their contents are unspecified.

So you need to learn about the Erase Remove Idiom. Here's an example:

#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>

void filter(std::vector<int>& vec)
{
    vec.erase(std::remove_if(begin(vec), end(vec),
                [](int n) { return n < 0 ||  n > 25; }),
            end(vec));
}

int main()
{
    std::vector<int> vec = {27, 1, 9, 6, 93, 73, 22, 25, 0, 18, 73};

    std::cout << "Original: ";
    std::copy(begin(vec), end(vec), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';

    filter(vec);
    std::cout << "Filtered: ";
    std::copy(begin(vec), end(vec), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
}

This erases all the entries from the return value of std::remove_if() to the end of the container. Then they actually are removed. The output is:

Original: 27 1 9 6 93 73 22 25 0 18 73 
Filtered: 1 9 6 22 25 0 18 

Note also that your comparison was incorrect and would always yield false, because there is no number that is both less than 0 and greater than 25.

Fred Larson
  • 60,987
  • 18
  • 112
  • 174