Home > Software engineering >  How do I use std::copy_if by both coping elements and removing those elements from the original cont
How do I use std::copy_if by both coping elements and removing those elements from the original cont

Time:12-16

Say I have a std::vector<int> with a simple operation to copy those elements which are even:

#include <vector>

int main()
{
    std::vector<int> v = {1, 2, 3, 4, 5, 6};
    std::vector<int> even;
    std::copy_if(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end()), std::back_inserter(even), [](int i){return i%2 == 0;});
        
    return 0;
}

My question how can I combine the above with any other method to remove the elements from vector v which was copied to vector even

CodePudding user response:

I wouldn't recommend trying to use std::copy_if here. Instead use std::stable_partition to move even elements to the end of v, copy this part to even using the vector constructor and then erase the copied elements from v:

int main()
{
    std::vector<int> v = { 1, 2, 3, 4, 5, 6 };
    
    // actual logic
    auto pivot = std::stable_partition(v.begin(), v.end(), [](int x) { return (x % 2) != 0;  });
    std::vector<int> even(pivot, v.end());
    v.erase(pivot, v.end());


    // display results
    std::cout << "v:\n";
    for (auto x : v)
    {
        std::cout << x << '\n';
    }

    std::cout << "even:\n";
    for (auto x : even)
    {
        std::cout << x << '\n';
    }

    return 0;
}

For objects that are expensive to copy, you may want to use std::move_iterator when creating even as suggested in @MooningDucks answer:

std::vector<int> even(std::move_iterator(pivot), std::move_iterator(v.end()));

CodePudding user response:

I would switch to using std::remove_if instead and have the function you pass to remove_if do the adding to the other vector. That gives you

std::vector<int> v = {1, 2, 3, 4, 5, 6};
std::vector<int> even;
v.erase(std::remove_if(v.begin(), v.end(), 
                       [&](auto val){ bool cond = (val % 2 == 0); 
                       if (cond) even.push_back(val); return cond; }), v.end());
  • Related