c vector удаление элемента

Я столкнулся с проблемой, когда мне нужно удалить последние элементы вектора, пока не будет выполнено определенное условие (для примера, пусть это будет элемент, не равный нулю)

Я написал этот код, он делает свое дело —

Но я бы предпочел найти алгоритм STL, который я могу использовать (я могу использовать find_if и затем стереть, но я бы хотел цикл один раз через элементы, которые я удаляю …)

Кроме того, я боюсь, что я могу вызвать здесь какой-то UB, должен ли я волноваться?

Решение

Ваш код может быть проще:

С помощью std::remove или же std::remove_if удалит все элементы на основе критериев, поэтому вы должны использовать std::find_if как Влад дал в своем ответе.

Другие решения

Вот пример. Он использует общую идиому для стирания векторов

У меня есть std::vector , и я хочу удалить n-й элемент. Как это сделать?

Чтобы удалить один элемент, вы можете сделать:

Или, чтобы удалить сразу несколько элементов:

Метод стирания на std::vector перегружен, поэтому, возможно, более ясный вызов

когда вы хотите удалить только один элемент.

Метод erase будет использоваться двумя способами:

Стирание одного элемента:

Стирание диапазона элементов:

На самом деле функция erase работает для двух профилей:

Удаление одного элемента

Удаление диапазона элементов

Так как std:: vec.begin() отмечает начало контейнера, и если мы хотим удалить i-й элемент в нашем векторе, мы можем использовать:

Если вы посмотрите внимательно, vec.begin() — это просто указатель на начальную позицию нашего вектора и добавление значения я к нему увеличивает указатель на позицию i, поэтому вместо этого мы можем получить доступ к указателю на i-й элемент по:

Итак, мы можем написать:

Если у вас есть неупорядоченный вектор, вы можете воспользоваться тем, что он неупорядочен и использует то, что я видел у Дэна Хиггинса в CPPCON

Поскольку порядок списка не имеет значения, просто возьмите последний элемент в списке и скопируйте его поверх элемента, который хотите удалить, затем нажмите и удалите последний элемент.

Если вы работаете с большими векторами (размером > 100 000) и хотите удалить множество элементов, я бы рекомендовал сделать что-то вроде этого:

Код принимает каждое число в vec, которое не может быть разделено на 3 и копирует его в vec2. Затем он копирует vec2 в vec. Это довольно быстро. Для обработки 20 000 000 элементов этот алгоритм занимает всего 0,8 с!

Я сделал то же самое с методом erase, и это занимает много и много времени:

Чтобы удалить элемент, используйте следующий способ:

Для более широкого обзора вы можете посетить: http://www.cplusplus.com/reference/vector/vector/erase/

Предыдущие ответы предполагают, что у вас всегда есть подписанный индекс. К сожалению, std::vector использует size_type для индексирования и difference_type для арифметики итератора, поэтому они не работают вместе, если вы включили «-Wconversion» и друзей. Это еще один способ ответить на вопрос, имея возможность обрабатывать как подписанные, так и unsigned:

Вот еще один способ сделать это, если вы хотите удалить элемент, найдя его с его значением в векторе, вам просто нужно сделать это на векторе.

это удалит ваше значение отсюда. Спасибо

Как насчет этого?

Я предлагаю прочитать это, так как я считаю, что это то, что вы ищете. https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom

Если вы используете, например,

Вы удалите n -th элемент вектора, но при удалении второго элемента все остальные элементы вектора будут смещены, а размер вектора будет равен -1. Это может быть проблемой, если вы перебираете вектор, поскольку vector size() уменьшается. Если у вас есть проблема, подобная этой, предложенная ссылка предложила использовать существующий алгоритм в стандартной библиотеке C++. и «удалить» или «удалить_if».

Подскажите, как корректно пройтись по вектору и удалить некоторые его элементы.
Т.е., корректно ли выполнять такие действия?

Или возникнут проблемы с итератором после удаления первого элемента?

Прочитал комментарии, всем спасибо за помощь

Пересмотрел код и понял, что не совсем полно поставил задачу:

Если воспользоваться советом @Harry, то тогда код можно же преобразовать к такому:

4 ответа 4

? Как по мне — понятнее и никаких проблем с итераторами. Вероятно, еще и быстрее, чем убирать по одному элементу.

Если перепишете check так, чтоб работал наоборот — то и лямбда-выражение (или bind ) не потребуется.

Если уж позарез нужен цикл — то воспользуйтесь тем, что erase возвращает итератор на элемент, следующий за удаленным:

Но учтите, что тут сложность — квадратичная, в отличие от remove_if (спасибо @pavel).

Оцените статью