CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11

Thread: remove_if (not)

  1. #1
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    remove_if (not)

    Basically, I have a string, and I want to remove all non alpha chars.

    I'm trying to do it using algorithm, so I thought I'd do something like this:

    Code:
    iString.erase(
        std::remove_if(iString.begin(), iString.end(), &isalpha),
        iString.end()
    );
    The problem is that this removes all the alpha, the oposite of what I want to do.

    I would use the algorithm std::copy_if or remove_if_not, but they don't exist. My other choice would be to pass std::not1(isalpha), but that doesn't work, since isalpha is not a function object.

    I could write this:
    Code:
    struct isalphafuntor : public std::unary_function<int,bool>
    {
        bool operator()(int iChar) const
        {
            return isalpha(iChar);
        }
    };
    But I would rather avoid it.

    So my question is this one:

    Can I, in a single line, pass the negated isalpha function to the remove if algorithm? or am I stuck with wrapping isalpha explicitly (or writting isnotalpha)?

  2. #2
    Join Date
    Nov 2003
    Posts
    1,902

    Re: remove_if (not)

    >> My other choice would be to pass std::not1(isalpha), but that doesn't work ...
    You can force the compiler to use the function instead of the macro with "&(::isalpha)". Or just use the C++ version from <locale>.

    gg

  3. #3
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: remove_if (not)

    Quote Originally Posted by Codeplug View Post
    >> My other choice would be to pass std::not1(isalpha), but that doesn't work ...
    You can force the compiler to use the function instead of the macro with "&(::isalpha)". Or just use the C++ version from <locale>.

    gg
    I don't understand your solution. The problem with not1 is that it takes a function object, and not a function, so that doesn't solve the problem. same with the one from locale.

    Or maybe I'm missing something?

  4. #4
    Join Date
    Nov 2003
    Posts
    1,902

    Re: remove_if (not)

    Predicate objects in STL can be functions or objects.

    gg

  5. #5
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: remove_if (not)

    Quote Originally Posted by Codeplug View Post
    Predicate objects in STL can be functions or objects.

    gg
    Yes, that's why I can pass isalpha as an argument. however, I'm having trouble building a not1(isalpha) function. Not1 takes only function objects.

    How can I negate a function, and pass the result as an argument?

  6. #6
    Join Date
    Jun 2006
    Location
    M31
    Posts
    885

    Re: remove_if (not)

    Quote Originally Posted by monarch_dodra View Post
    Yes, that's why I can pass isalpha as an argument. however, I'm having trouble building a not1(isalpha) function. Not1 takes only function objects.

    How can I negate a function, and pass the result as an argument?
    That's what std::ptr_fun from the functional header's for.

  7. #7
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: remove_if (not)

    Quote Originally Posted by Plasmator View Post
    That's what std::ptr_fun from the functional header's for.
    *facepalms* thankyou Plasmator, that's what I was looking for. And here is what I wrote.

    Code:
    void lcase(std::string& ioString)
    {
        ioString.erase(
            std::remove_if(ioString.begin(), ioString.end(), std::not1(std::ptr_fun(&isalpha))),
            ioString.end()
        );
        std::transform(ioString.begin(), ioString.end(), ioString.begin(), std::ptr_fun(&tolower));
    }
    I'm wondering though, which is more efficient?
    Code:
    std::transform(ioString.begin(), ioString.end(), ioString.begin(), &tolower);
    or
    std::transform(ioString.begin(), ioString.end(), ioString.begin(), std::ptr_fun(&tolower));
    Is there a difference in performance? I heard function objects are faster because the compiler can inline them, but in this case, the end result is that isalpha still has to be called?

  8. #8
    Join Date
    Nov 2003
    Posts
    1,902

    Re: remove_if (not)

    >> That's what std::ptr_fun from the functional header's for.
    Right...sorry, I got stuck on function vs. macro. std::ptr_fun will make it adaptable when it's needed.
    Code:
    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <functional>
    #include <cctype>
    using namespace std;
    
    int main()
    {
        string s = "a1b23c";
        s.erase(remove_if(s.begin(), s.end(), not1(ptr_fun(&(::isalpha)))), 
                s.end());
        cout << s << endl;
        return 0;
    }//main
    gg

  9. #9
    Join Date
    Nov 2003
    Posts
    1,902

    Re: remove_if (not)

    >> I'm wondering though, which is more efficient?
    Premature optimization?...

    I would say they are identical since std::ptr_fun will most likely be optimized away.

    For maximum [premature] optimization, you could write a predicate object that used the macro version of tolower. Or assume A-Z and a-z and do it yourself.

    gg

  10. #10
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: remove_if (not)

    Quote Originally Posted by Codeplug View Post
    >> I'm wondering though, which is more efficient?
    Premature optimization?...

    I would say they are identical since std:tr_fun will most likely be optimized away.

    For maximum [premature] optimization, you could write a predicate object that used the macro version of tolower. Or assume A-Z and a-z and do it yourself.

    gg
    I wouldn't call it premature optimization but more of a best practice. I'm not looking to optimize, just to find out which one is best, in general. Thanks anyways

  11. #11
    Join Date
    Aug 2005
    Location
    San Diego, CA
    Posts
    1,054

    Lightbulb Re: remove_if (not)

    Quote Originally Posted by monarch_dodra View Post
    I'm wondering though, which is more efficient?
    Code:
    std::transform(ioString.begin(), ioString.end(), ioString.begin(), &tolower);
    or
    std::transform(ioString.begin(), ioString.end(), ioString.begin(), std::ptr_fun(&tolower));
    Is there a difference in performance? I heard function objects are faster because the compiler can inline them, but in this case, the end result is that isalpha still has to be called?
    I've read the same thing but I don't think that it justifies turning a library function into a functor in this case. I have a hard time believing that it would significantly improve your program. If you were writing your own predicate, as opposed to using a std library function, then I would always choose a functor over writing a global or static member function. Even then I'm not sure if the performance boost is really significant. I do it because I like the object orientedness of using functors, for lack of a better phrase. When passing a predicate by value to an algorithm, the functor concept seems more intuitive to me but I have never even bothered to measure the performance difference.

    If you really wanted to know, you'd have to write a couple of sample programs and study the assembly code of each. You could also use some timestamps or a profiling tool to study the differences if you want. it might be useful to do that one time just to see for yourself what kind of a difference there is.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured