0

I get run-time error and I suspect it's because of this block of code, I'd like to know how to iterate over a set and erase from it in the middle.

    for (auto it : a) {
        if (freq[it.first] == 1 || freq[it.second] == 1)
            a.erase(it);
    }

I tried this solution which I found on another question but it still doesn't seem to work:

    for (set<pair<int, int> >:: iterator it = a.begin(); it != a.end();)
    {
        cout << it->first << " " << it->second << endl;
        if (freq[it->first] == 1 || freq[it->second] == 1)
        {
            removed = true;
            a.erase(it);
        }
        else
        {
            ++it;
        }
    }
  • You can't erase when using ranged `for` loops. – HolyBlackCat Mar 26 '18 at 15:46
  • Could you elaborate more on that please? – Mostafa Omar Mar 26 '18 at 15:47
  • I mean that you have to use iterators directly, i.e. `auto it = a.begin(); while (it != a.end()) {... it++;}`. – HolyBlackCat Mar 26 '18 at 15:50
  • alright that worked, thanks alot. But I still don't quite understand what's the difference between increasing the iterator regularly or like this since we increment it in both cases of the if condition anyway. – Mostafa Omar Mar 26 '18 at 15:57
  • @MostafaOmar It has to do with iterator invalidation. `container.erase(iterator)` invalidates the iterator(you can't use it anymore). `container.erase(iterator++)` on the other hand sends the current value of `iterator` to `erase` but then increments it before it is erased so you still have a valid iterator. – NathanOliver Mar 26 '18 at 15:59
  • Why not just use [std::remove_if](http://en.cppreference.com/w/cpp/algorithm/remove) ? – Jesper Juhl Mar 26 '18 at 16:05
  • @JesperJuhl: Because `std::remove_if` cannot be used with a set. – Christian Hackl Mar 26 '18 at 16:08

1 Answers1

0

this solved it:

for (set<pair<int, int> >:: iterator it = a.begin(); it != a.end();/* blank */)
{
    cout << it->first << " " << it->second << endl;
    if (freq[it->first] == 1 || freq[it->second] == 1)
    {
        removed = true;
        it = a.erase(it);
    }
    else
    {
        ++it;
    }
}
  • 1
    You could use `it = a.erase(it)` instead. Your one works with sets, but not with e.g. vectors, and this one always works. – HolyBlackCat Mar 26 '18 at 16:22