Vectors trouble

I've searched through the vectors portion of this website and I've been trying to figure out a way to remove a specific value that a user inputs from a vector array. I'm guessing there isn't a member function.

An idea I had would be to use a linear search then if the value is found then it moves that value to the last element so I could then use the "pop_back" member function.

Ideas? Comments?
If v is the vector and value is the value that you want to search for and remove you can do
1
2
3
4
5
6
auto it = std::find(v.begin(), v.end(), value);
if (it != v.end())
{
	*it = std::move(v.back());
	v.pop_back();
}
Last edited on
What is "auto" key word?
C++11's automatic type inference keyword.
Your compiler may, or may not, support this feature.

You could use std::remove() instead:
http://cplusplus.com/reference/algorithm/remove/

Edit: I made major mistakes from here onward. See Peter87's post for details.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> vi;

    vi.push_back(1);
    vi.push_back(666);
    vi.push_back(2);
    vi.push_back(3);

    std::remove(vi.begin(), vi.end(), 666);
    vi.pop_back();

    for (std::vector<int>::const_iterator ci = vi.begin(); ci != vi.end(); ++ci)
        std::cout << *ci << std::endl;
}


Alternatively, std::vector::erase().
http://cplusplus.com/reference/vector/vector/erase/

Edit: the above code has a bug: you need to check if the removal operation was successful before you pop the end of the vector. It would be nice if std::remove() managed this itself, though.
1
2
if (std::remove(vi.begin(), vi.end(), 666) != vi.end())
    vi.pop_back();

Last edited on
In my example auto can be replaced by the iterator type. If it's an vector of int it could be written as
1
2
3
4
5
6
std::vector<int>::iterator it = std::find(v.begin(), v.end(), value);
if (it != v.end())
{
	*it = v.back();
	v.pop_back();
}

std::move was used because some objects are more efficient to move than to copy. For simple types like int there is no difference. Moving is a C++11 feature and you don't need to use it. If you can't use std::move but still want to avoid the costly copying you could use std::swap. Using std::swap will be slower for simple types like int but for some types like std::string, std::vector, etc. it is often more efficent because it avoids the need to have to copy all the elements stored in the string/vector.


If you are going to use std::remove note that it will have to move all elements after a removed element (it doesn't use the pop_back() trick) so it might be slower. Also note that std::remove will remove all elements that match, so in Catfish's example, if there was 5 elements with the value 666 it would remove all 5 elements. My example will just remove the first if there is more than one match.

std::remove doesn't really remove any objects from the container. It just moves the objects and returns an iterator to the new end, leaving garbage at the end. Catfish's code assumes there there is exactly one element removed, and his edit assumes no more than one element was removed. A better way to use std::remove is to pass the return value to erase like this:
vi.erase(std::remove(vi.begin(), vi.end(), 666), vi.end());
No need to use if statements or anything. This will always work.
erase-remove is really the most common way to do this kinda thing.
http://en.m.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove
Thank you all for your input. It was really helpful!
in line 1 of Peter87's code is "std::find" in a preloaded Visual studios Library?
It's in the algorithm header.
http://cplusplus.com/reference/algorithm/find/
Topic archived. No new replies allowed.