Я смотрел документацию API для stl vector и заметил, что не существует метода для векторного класса, который позволил бы удалить элемент с определенным значением. Это похоже на общую операцию, и кажется странным, что нет встроенного способа сделать это.
Как удалить элемент из stl-вектора с определенным значением?
Ответ 1
std::remove
самом деле не стирает элемент из контейнера, но возвращает новый конечный итератор, который можно передать в container_type::erase
для РЕАЛЬНОГО удаления дополнительных элементов, которые теперь находятся в конце контейнера:
std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());
Ответ 2
Если вы хотите удалить элемент , следующее будет более эффективным.
std::vector<int> v;
auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
v.erase(it);
или вы можете избежать накладных расходов на перемещение элементов, если заказ не имеет для вас значения:
std::vector<int> v;
auto it = std::find(v.begin(), v.end(), 5);
if (it != v.end()) {
using std::swap;
// swap the one to be removed with the last element
// and remove the item at the end of the container
// to prevent moving all items after '5' by one
swap(*it, v.back());
v.pop_back();
}
Ответ 3
Используйте глобальный метод std:: remove с итератором begin и end, а затем используйте std::vector.erase для фактического удаления элементов.
Ссылки на документацию
std:: remove http://www.cppreference.com/cppalgorithm/remove.html
std::vector.erase http://www.cppreference.com/cppvector/erase.html
std::vector<int> v;
v.push_back(1);
v.push_back(2);
//Vector should contain the elements 1, 2
//Find new end iterator
std::vector<int>::iterator newEnd = std::remove(v.begin(), v.end(), 1);
//Erase the "removed" elements.
v.erase(newEnd, v.end());
//Vector should now only contain 2
Спасибо Джим Бак за то, что он указал на мою ошибку.
Ответ 4
Если у вас есть несортированный вектор, вы можете просто поменять его на последний векторный элемент, затем resize()
.
С помощью заказанного контейнера вам будет лучше всего std::vector::erase()
. Обратите внимание, что существует std::remove()
, определенный в <algorithm>
, но это фактически не стирает. (Внимательно прочитайте документацию).
Ответ 5
В других ответах рассказывается, как это сделать хорошо, но я думал, что также хочу сказать, что это не так странно, что это не в векторном API: это неэффективный, линейный поиск через вектор для значения, затем путём копирования, чтобы удалить его.
Если вы делаете эту операцию интенсивно, по этой причине стоит подумать о std:: set.
Ответ 6
Более короткое решение (которое не заставляет вас повторять имя вектора 4 раза) было бы использовать Boost:
#include <boost/range/algorithm_ext/erase.hpp>
// ...
boost::remove_erase(vec, int_to_remove);
Ответ 7
См. также std:: remove_if, чтобы использовать предикат...
Вот пример из приведенной выше ссылки:
vector<int> V;
V.push_back(1);
V.push_back(4);
V.push_back(2);
V.push_back(8);
V.push_back(5);
V.push_back(7);
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
// The output is "1 4 2 8 5 7"
vector<int>::iterator new_end =
remove_if(V.begin(), V.end(),
compose1(bind2nd(equal_to<int>(), 0),
bind2nd(modulus<int>(), 2)));
V.erase(new_end, V.end()); [1]
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
// The output is "1 5 7".
Ответ 8
Из c++ 20:
Функция, не являющаяся членом, представила std::erase
, которая принимает вектор и значение для удаления в качестве входных данных.
например:
std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);
Ответ 9
Если вы хотите сделать это без каких-либо дополнительных включений, выполните следующие действия.
vector<IComponent*> myComponents; //assume it has items in it already.
void RemoveComponent(IComponent* componentToRemove)
{
IComponent* juggler;
if (componentToRemove != NULL)
{
for (int currComponentIndex = 0; currComponentIndex < myComponents.size(); currComponentIndex++)
{
if (componentToRemove == myComponents[currComponentIndex])
{
//Since we don't care about order, swap with the last element, then delete it.
juggler = myComponents[currComponentIndex];
myComponents[currComponentIndex] = myComponents[myComponents.size() - 1];
myComponents[myComponents.size() - 1] = juggler;
//Remove it from memory and let the vector know too.
myComponents.pop_back();
delete juggler;
}
}
}
}
Ответ 10
Есть два способа, которыми вы можете использовать, чтобы стереть элемент, в частности. давайте возьмем вектор
std :: vector < int > v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(50);
1) Неэффективный способ: хотя это кажется довольно эффективным, но это не потому, что функция стирания удаляет элементы и сдвигает все элементы влево на 1., поэтому его сложность будет O (n ^ 2)
std :: vector < int > :: iterator itr = v.begin();
int value = 40;
while ( itr != v.end() )
{
if(*itr == value)
{
v.erase(itr);
}
else
++itr;
}
2) Эффективный способ (РЕКОМЕНДУЕТСЯ): он также известен как идиомы ERASE - REMOVE.
- std :: remove преобразует данный диапазон в диапазон со всеми элементами, которые сравниваются не равными данному элементу, смещенными в начало контейнера.
- Таким образом, на самом деле не удаляйте соответствующие элементы. Он просто сдвинул несоответствие к началу и дает итератору новый действительный конец. Это просто требует сложности O (n).
Вывод алгоритма удаления:
10 20 30 50 40 50
в качестве возвращаемого типа удаления используется итератор для нового конца этого диапазона.
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);
Теперь используйте функцию стирания векторов для удаления элементов с нового конца на старый конец вектора. Требуется O (1) время.
v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );
так что этот метод работает в O (N)