Обход мультимножества от нижней границы

Я хочу начать с итератора low_bound моего целевого значения в мультимножестве, затем удалить все его вхождения и продолжить переход к следующим значениям того же мультимножества, я делаю что-то вроде...

       multiset<int>s={....};
 auto it=s.lower_bound(target); 
 
 while(it!=s.end()){
  if(s.find(target)!=s.end())
    it=s.erase(target);
  else it++;
}

Но у меня выдает ошибку...

      Line 36: Char 12: error: no viable overloaded '='
        it4=x.erase(99);
        ~~~^~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_tree.h:326:12: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'std::set<int, std::less<int>, std::allocator<int>>::size_type' (aka 'unsigned long') to 'const std::_Rb_tree_const_iterator<int>' for 1st argument
    struct _Rb_tree_const_iteratorrgument

Есть ли разница в итераторах s.lower_bound(target) и s.erase(target)? Мне особенно нужно продолжать перемещение таким образом, поскольку я знаю другой способ продолжать поиск и удаление цели до тех пор, пока ее больше нельзя будет найти в наборе.

1 ответ

Аstd::setможет иметь только один экземпляр любого значения, поэтому однократный вызов удаляет все возможные экземпляры этого значения. Нет необходимости сначала вызывать low_bound или что-то в этом роде. Например:

      int main(){
    std::set<int> x = { 1, 2, 3, 4, 5};

    x.erase(2);
    for (auto const &p : x)
        std::cout << p << " ";    
}

Производит:

      1 3 4 5

Live on Coliru

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

      #include <set>
#include <iostream>

int main() { 
    std::multiset<int> s { 1, 2, 3, 4 ,4, 5, 2, 1, 3};
    auto p = s.equal_range(2);

    s.erase(p.first, p.second);

    for (auto const & v : s)
        std::cout << v << " ";
    std::cout << "\n";
}

Результат:

      1 1 3 3 4 4 5 

Live on coliru

Но вы также можете заметить, что в этом случае нам по-прежнему не нужно указывать диапазон для прохождения. Мы по-прежнему можем просто указать значение, которое нужно стереть, и все его экземпляры будут удалены:

      #include <set>
#include <iostream>

int main() { 
    std::multiset<int> s { 1, 2, 3, 4 ,4, 5, 2, 1, 3};

    s.erase(2);

    for (auto const & v : s)
        std::cout << v << " ";
    std::cout << "\n";
}

[Тот же результат, что и выше]

Live on Coliru

было бы полезно, если бы (например) мы хотели стереть все экземпляры этого значения в наборе, кроме одного. В этом случае мы могли бы (например) вызватьequal_rangeи либо увеличить его.firstили уменьшить его.second, тогда позвониerase, стирая все это значение, кроме одного.

Другие вопросы по тегам