Search code examples
c++iterator

Insert into vector with conditional iterator


Say I have a vector with various entries, which I want to insert into another vector, while leaving out entries that satisfy a condition.

For example, I want to insert a vector while leaving out all three's.

{1, 3, 2, 3, 4, 5, 3} -> { /* previous content, */ 1, 2, 4, 5}

What I came up with so far uses std::partition, which does not preserve the relative order and rearranges the source vector.

std::vector<int> source({1, 3, 2, 3, 4, 5, 3});
std::vector<int> target;

auto partition = std::partition(std::begin(source),
                   std::end(source), [](const auto& a) { return a == 3; });
target.insert(std::begin(target), partition, std::end(source));

What I am looking for is more of an iterator that checks a condition and moves on if the condition is not satisfied. Something like this:

target.insert(std::begin(target),
              conditional_begin(source, [](const auto& a) { return a != 3; }),
              conditional_end(source));

I suppose a conditional_end function would be necessary, since std::end would return a different iterator type than conditional_begin.

Maybe I have overlooked something, so my questions are:

  • Does the standard library provide something similar?
  • Is there a different easy way to achieve my goal?
  • Is there an easy way to implement the conditional iterator functionality?

Solution

  • Is there a different easy way to achieve my goal?

    Yes, the standard already has this functionality built in. The function you are looking for is std::copy_if.

    std::vector<int> source({1, 3, 2, 3, 4, 5, 3});
    std::vector<int> target;
    
    std::copy_if(source.begin(), 
                 source.end(), 
                 std::back_inserter(target), [](auto val){ return val != 3; });
    

    Here, std::back_inserter(target), will call push_back on target for each element that the predicate returns true.