Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing elements from vector using remove_if

I am trying to remove vector elements using remove_if. But unsuccessfully. What am I doing wrong?

Here's my code:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

void printme(std::vector<int>& a){
    for(const auto& item: a)
    std::cout << item << std::endl;
}

int main()
{
    std::vector<int> a {1, 2, 3, 4, 5, 6};
    printme(a);  
    a.erase( (std::remove_if(a.begin(), a.end(), [](const int& x){
        return x == 2;
        }), a.end()));
    printme(a);
}

My output is just:

1 2 3 4 5 6

Expected output:

1 2 3 4 5 6 1 3 4 5 6

like image 445
wair92 Avatar asked Jul 31 '18 05:07

wair92


People also ask

How do I remove an item from a vector file?

All the elements of the vector are removed using clear() function. erase() function, on the other hand, is used to remove specific elements from the container or a range of elements from the container, thus reducing its size by the number of elements removed.

How do you delete an element from a vector by its value?

You need to use std::remove algorithm to move the element to be erased to the end of the vector and then use erase function. Something like: myVector. erase(std::remove(myVector. begin(), myVector.

How do I remove an element from a vector string?

To remove all copies of an element from a vector , you can use std::remove like this: v. erase(std::remove(v. begin(), v.

How do I remove multiple elements from a vector file?

If you need to remove multiple elements from the vector, the std::remove will copy each, not removed element only once to its final location, while the vector::erase approach would move all of the elements from the position to the end multiple times.

How to remove elements from a vector in C++?

Methods used to remove elements from vector are: 1 vector::pop_back () 2 vector::pop_front () 3 vector::erase () 4 vector::clear () 5 remove (first,last,val) 6 remove_if () 7 remove_copy (first,last,result,val)

How to remove element at specified index in Java vector?

Element at the specified index in Java vector can be removed using remove () method. this method is present in java.util.Vector class. We can pass index of the element which will be removed as an argument. remove () method return method returns the element that was removed. Parameters: The index of the element to be removed.

What is the difference between erase () and remove () in a vector?

erase () causes large amount of copies while remove () just does a logical delete and leaves vector unchanged by moving element around. If you need to remove multiple elements, remove () will copy elements only once to its final position while erase () would do this multiple times.

What is the difference between insert and remove in vector array?

Insertion at the end takes linear time, as sometimes there may be a need of extending the array. Removing the last element takes constant time because no resizing happens. Inserting or removing element in the middle is linear in time. vector.size () Returns the number of elements in vector.


4 Answers

You are using an overload of the std::vector::erase() member function that takes a single iterator as parameter. As the argument to erase() you are providing the iterator a.end(), since the following expression:

(std::remove_if(a.begin(), a.end(), [](const int& x){ return x == 2; }), a.end()))

evaluates to a.end() (i.e., because of the comma operator).

The iterator passed to the overload of erase() that takes a single iterator must be dereferenceable. However, the iterator a.end() is not dereferenceable, therefore, the call to erase() results in undefined behavior.


To use the overload that takes two iterators, remove the parenthesis surrounding the call to std::remove_if:

a.erase(std::remove_if(a.begin(), a.end(), [](const int& x){
        return x == 2;
        }), a.end());
like image 116
ネロク・ゴ Avatar answered Nov 02 '22 09:11

ネロク・ゴ


You're adding superfluous parentheses, change it to

a.erase( std::remove_if(a.begin(), a.end(), [](const int& x){
    return x == 2;
    }), a.end());

Note that the comma operator just returns the last operand, that means you're passing a.end() to erase, which leads to UB.

like image 45
songyuanyao Avatar answered Nov 02 '22 11:11

songyuanyao


The other answers have pointed out what the problem was. I want to say, it will be easier to notice these kinds of problems by simplifying your code.

I suggest using:

int main()
{
   std::vector<int> a {1, 2, 3, 4, 5, 6};
   printme(a);  

   auto it = std::remove_if(a.begin(), a.end(), [](const int& x){ return x == 2; });
   a.erase(it, a.end());

   printme(a);
}
like image 38
R Sahu Avatar answered Nov 02 '22 11:11

R Sahu


You just had too many parentheses in the function call.

a.erase(std::remove_if(a.begin(), a.end(), [](const int& x) {return x == 2;}), a.end());

Just remove one parentheses before the std::remove_if and at the end of the call.

like image 37
Petok Lorand Avatar answered Nov 02 '22 10:11

Petok Lorand