ChatGPT解决这个技术问题 Extra ChatGPT

C++ Erase vector element by value rather than by position? [duplicate]

This question already has answers here: How do I remove an item from a stl vector with a certain value? (12 answers) Closed 6 years ago.

vector<int> myVector;

and lets say the values in the vector are this (in this order):

5 9 2 8 0 7

If I wanted to erase the element that contains the value of "8", I think I would do this:

myVector.erase(myVector.begin()+4);

Because that would erase the 4th element. But is there any way to erase an element based off of the value "8"? Like:

myVector.eraseElementWhoseValueIs(8);

Or do I simply just need to iterate through all the vector elements and test their values?

@BenVoigt: your question is quite arrogant - clearly the guy cannot answer it, what YOU should have done is create an answer that covers all the cases you mention.
@slashmais: Oh nonsense, my clarifying question was quite simple and doesn't require an expert programmer to answer. And there's no way I could cover all possible values of "what do you want to do?" for all three of the cases. Just for the case of "no matching elements" possible behaviors include "nothing", "throw an exception", "return an error", "exit the process (possibly via assert())", "log a message to std::cerr"... and even those aren't exhaustive. No, the asker of the question needs to state the error handling policy, and whether finding no matches even is an error.
... case of QED. i think

C
Community

How about std::remove() instead:

#include <algorithm>
...
vec.erase(std::remove(vec.begin(), vec.end(), 8), vec.end());

This combination is also known as the erase-remove idiom.


@jak: Take a look at the description of remove(): It moves all values not equal to the value passed to the beginning of the range [begin,end). With your example in the question you'd get 5,9,2,0,7,7. As remove() however returns an iterator to the new end, vec.erase() can remove the obsolete elements (i.e. the second 7 here) if that is needed.
@Assimilater: It is not necessary.
@GeorgFritzsche Why can't you just answer his question instead of sending him a link? Yes, it is O(n)
@AlisherKassymov Because the answer is easily found there. And it's a better approach for learning. Different people have different approaches, something worth respecting.
The dumb part of this algorithm is that remove doesn't stop when it finds the first match. It is inefficient to keep comparing the rest of the list. So this is great if there are potentially multiple copies of the same value in the vector, but it isn't a good answer for the common scenario of a vector of unique values. In that case, the std::find is a better option.
C
Community

You can use std::find to get an iterator to a value:

#include <algorithm>
std::vector<int>::iterator position = std::find(myVector.begin(), myVector.end(), 8);
if (position != myVector.end()) // == myVector.end() means the element was not found
    myVector.erase(position);

This is good if you only expect one occurence of that value.
@TomášZato: Or want only one removed, which seems to be the case for this question.
For removing all the values, initialize position = myVector.begin() and enclose everything in a while(position != myVector.end()) loop
Error C2676 binary '==': 'action' does not define this operator or a conversion to a type acceptable to the predefined operator in xutility. Literally any method I come across for this example gives me this error.
Voted down because this is really not the way you should do this (the most upvoted answer is the correct way).
C
Community

You can not do that directly. 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.end(), 8), myVec.end());. See this erasing elements from vector for more details.


k
kometen

Eric Niebler is working on a range-proposal and some of the examples show how to remove certain elements. Removing 8. Does create a new vector.

#include <iostream>
#include <range/v3/all.hpp>

int main(int argc, char const *argv[])
{
    std::vector<int> vi{2,4,6,8,10};
    for (auto& i : vi) {
        std::cout << i << std::endl;
    }
    std::cout << "-----" << std::endl;
    std::vector<int> vim = vi | ranges::view::remove_if([](int i){return i == 8;});
    for (auto& i : vim) {
        std::cout << i << std::endl;
    }
    return 0;
}

outputs

2 4 6 8 10 ----- 2 4 6 10