-1

can somebody help me with this function: suppose that I need to remove all even numbers from a vector using reference: can I do that? Is the push_back correct or should I use something else?

void evenRemoe(vector<int>& arr) {
    for(int i = 0; i < arr.size(); i++) {
        if(arr[i] % 2 != 0) {
            push_back(arr[i]);
        }  
    }
}
chi
  • 111,837
  • 3
  • 133
  • 218
Marinette
  • 1
  • 3
  • 6
    Why would you want to *push* something you are trying to *remove*? – Remy Lebeau Feb 08 '22 at 23:43
  • 1
    No, push_back isn't right (and I expect you knew that, otherwise you wouldn't have used it, and wouldn't be here now). You may find the [erase-remove-if idiom](https://stackoverflow.com/questions/39019806/using-erase-remove-if-idiom) worth a read. – WhozCraig Feb 08 '22 at 23:44

5 Answers5

6

Using push_back adds elements so that's not going to work.

You can use std::erase_if with a functor, like a lambda or other function acting as a unary predicate, to decide what elements that should be removed.

void evenRemoe(std::vector<int>& arr) {
    std::erase_if(arr, [](int i) { return i % 2 == 0; });
}

Prior to C++20 you could implement the erase–remove idiom

#include <algorithm>
void evenRemoe(std::vector<int>& arr) {
    arr.erase(std::remove_if(arr.begin(), arr.end(),
                             [](int i) { return i % 2 == 0; }),
              arr.end());
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
3

No, push_back() is not the correct thing to use. That is meant for adding values, not removing them.

Also, your code is actually looking for odd values, not even values.

You can use std::vector::erase() to remove individual values, eg:

void evenRemoe(vector<int>& arr){
    for(size_t i = 0; i < arr.size();){
        if (arr[i] % 2 == 0){
            arr.erase(arr.begin()+i);
        }else{
            ++i;
        }
    }
}

Alternatively, consider using the Erase-Remove idiom via std::remove_if() and std::vector::erase(), eg:

#include <algorithm>

void evenRemoe(vector<int>& arr){
    arr.erase(
        std::remove_if(arr.begin(), arr.end(),
            [](int value){ return (value % 2) == 0; }
        ),
        arr.end()
    );
}

Or, in C++20, via std::erase_if(), eg:

void evenRemoe(vector<int>& arr){
    std::erase_if(arr,
        [](int value){ return (value % 2) == 0; }
    );
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
3

push_back is a method of std::vector for appending an element to the end of the vector, not removing. What you need is one of the erase methods.

However, you should be careful while erasing elements of the vector you're iterating over. Care must be taken to avoid incrementing the index when you remove the element.

The better way to do this is to use std::remove_if algorithm instead of iterating the vector yourself.

void evenRemove(vector<int>& arr) {
    auto it = std::remove_if(arr.begin(), arr.end(),
        [](int n) { return (n % 2) == 0; });
    arr.erase(it, arr.end());
}

Despite the name, std::remove_if doesn't actually remove any elements from the vector. Instead, it moves the elements that match the predicate (in our case - all even integers) to the end of the vector and returns an iterator pointing to the first of such elements. Therefore, to actually remove the elements you need to call erase with the iterators denoting the tail of the vector that contains the even integers.

Andrey Semashev
  • 10,046
  • 1
  • 17
  • 27
0

From C++20 onwards you can use std::erase_if() , Prior to c++20 erase-remove idiom used to be the solution of this problem.

v.erase(std::remove_if(v.begin(), v.end(), is_even), v.end());

Where is_even is a functor

0

Remove multiple element from vector using iterator. Just take care that when we erase using iterator,it goes invalid.

int main(){
        vector<int> vec={1,2,3,4,5,6,7,8,9};
        for(auto it=vec.begin();it!=vec.end();){
           if(*it%2==0)
               vec.erase(it);
           else
               it++;
        }
        for(auto i:vec){
            cout<<i<<" ";
        }
        return 0;
    }

output:1 3 5 7 9

2nd method

int main(){
    vector<int> vec={1,2,3,4,5,6,7,8,9};
    vec.erase(remove_if(vec.begin(),vec.end(),[](int i){
        return i%2==0;
    }),vec.end());

    for(auto i:vec)
        cout<<i<<" ";
    
    return 0;
}