Удаление по индексу из вектора C ++ с использованием remove_if

Мы можем использовать remove_if в C ++ для удаления элементов из вектора за линейное время на основе предиката, который работает с элементами.

bool condition(double d) {...}

vector<double> data = ...
std::remove_if (data.begin(), data.end(), condition);

Что если мое состояние зависит не от значений, а от показателей? Другими словами, если я хотел удалить все нечетно-проиндексированные элементы, или какой-то произвольный набор индексов и т. Д.?

bool condition(int index) {//returns whether this index should be removed}

vector<double> data = ...
std::remove_if (data.begin(), data.end(), ???);

6

Решение

Вы можете использовать арифметику указателей, чтобы найти индекс определенного элемента, который std::remove_if переходит к предикату:

std::remove_if(data.begin(), data.end(),
[](const double& d) { return (&d - &*data.begin()) % 2); });

Обратите внимание, что remove_if передает результат разыменования итератора, и это гарантированно будет reference согласно Таблице 106 — Требования к итераторам в Стандарте.

6

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

Я фактически сделал аккаунт только для этого. Используйте awesomeyi ответ. Это способ чище.

int count = 0;
auto final = std::remove_if (data.begin(), data.end(), [&count](const double d) {
return (count++) % 2;
});

Стандарт гласит, что предикат применяется точно в последний раз. И remove_if работает с ForwardIterators.

Это подразумевает, что предикат применяется только один раз в том же порядке, в котором он первоначально появился в последовательности.

Если, конечно, библиотека контролирует вас, сохраняя внутренние копии ForwardIterator.

5

Воспользуйтесь тем, что lambas может захватывать переменные. Быстрый пример:

vector<double> data = {5, 3, 6, 7, 8};

int count = 0;
auto final = std::remove_if (data.begin(), data.end(), [&](const double d) {
bool b = false;
if(count % 2) b = true;
++count;
return b;
});

for(auto beg = data.begin(); beg != final; ++beg)
cout << *beg << endl;

Код напечатает: 5 6 8

1
По вопросам рекламы [email protected]