удалить, если — В c ++ безопасно ли использовать std :: numeric_limits & lt; double & gt; :: max () в качестве специального & quot; флага & quot ;?

Дано

std::vector<double> a;
std::vector<int> ind;

где ind является 1отсортировано в порядке возрастания.

Я хочу сделать эквивалент следующего:

for (auto it=ind.rbegin();it!=ind.rend();it++) a.erase(a.begin() + *it);

Я придумал это:

for (auto it=ind.begin();it!=ind.end();it++)
a[*it] = std::numeric_limits<double>::max();
std::erase(std::remove(a.begin(),a.end(),std::numeric_limits<double>::max()),a.end());

Это очень быстро, но не правильно использовать std :: numeric_limits :: max () в качестве флага в этом контексте.

Конечно, чувства не должны играть слишком много в уравнении … четкое сравнение двойных значений в std :: remove безопасно, и на практике этот вектор никогда не возникнет в этом в рабочем приложении, поэтому все должно быть в порядке, нет?

Есть мысли по этому поводу?


1) Ссылка комментарий ОП. Альф

3

Решение

Давайте посмотрим на ваш «базовый» код, который вы говорите, что хотите сделать «эквивалент»:

std::vector<double> a;
std::vector<int> ind;

for (auto it = ind.rbegin(); it != ind.rend(); it++)
a.erase(a.begin() + *it);

Из этого мы получаем то, что ind вектор индексов в a которые должны быть удалены, и что они отсортированы по возрастанию. Эти индексы должны быть удалены из a, Я предполагаю, что ваша цель — сделать это эффективно с точки зрения пространства и времени.

Если вы думаете об этом с точки зрения минимального количества требуемых операций, вы должны сдвинуть многие / большинство / все элементы в a чтобы стереть те, которые указаны ind, Ты не хочешь erase() несколько раз, потому что это означает смещение некоторых элементов более одного раза. Одно оптимальное решение (в общем случае не навязывание особых требований к значениям в a) выглядит так:

size_t slow = 0; // where we are currently copying "to"std::vector<int> inditer = ind.begin();
for (size_t fast = 0; fast != a.size(); ++fast) {
if (inditer != ind.end() && *inditer == fast) {
// "remove" this element by ignoring it
++inditer;
} else {
a[slow] = a[fast];
++slow;
}
}
a.resize(slow);

Теперь вы могли бы переформулировать это, используя алгоритмы STL и пользовательский предикат (функтор), который запоминает свою «текущую» позицию в ind, но это не будет намного меньше кода, и это может быть сложнее понять.

3

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


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