Erase Elements from a Set while Iterating in C++ and Generic erase_if()

Set:

A Set is used in programming to store unique values of a list while also automatically providing an ordering to its elements. The ordering is set to ascending by default.

The insert() method is used to insert the elements. If the same value is inserted more than once, the set automatically deletes the duplicates and stores only one copy of that variable.

The erase() method is used to remove the Set’s components.

Removing elements from set while iterating through it

There are several ways to remove elements from set while iterating some of them are:

Method #1:Using erase() function

The member function erase() in std::set takes an iterator as an argument and removes it from the set.
However, this renders the passed iterator useless. It returns an iterator from c++11 onwards that points to the element after the last deleted element. We may use this as a starting point for further iteration.

Let’s now delete all string entries from strings longer than 2 characters.

Below is the implementation:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    // creating a string set and initializing with some
    // strings
    set<string> stringset = { "Hello", "this",       "is",
                              "this",  "BTechGeeks", "on" };
    // printing the set before removing strings
    cout << "Printing the set before removing : " << endl;
    for (auto val : stringset)
        cout << val << " ";
    cout << endl;
    // creeating an iterator which points to first element
    // of the set
    set<string>::iterator itr = stringset.begin();
    // Traverse the set till the end
    while (itr != stringset.end()) {
        if (itr->size() > 2) {
            // removing the string from stringset if length
            // of it is greater than 2
            itr = stringset.erase(itr);
        }
        else
            itr++;
    }
    // printing the set after removing strings
    cout << "Printing the set after removing :" << endl;
    for (auto val : stringset)
        cout << val << " ";
    cout << endl;
    return 0;
}

Output:

Printing the set before removing : 
BTechGeeks Hello is on this 
Printing the set after removing :
is on

Method #2:Using erase_if function

Let’s make a generic function that can be used with a set, vector, or list to remove elements by iterating based on a condition. For example, let’s use the generic function to remove all strings from a set with a size greater than 2 by using it.

Below is the implementation: 

#include <bits/stdc++.h>
using namespace std;
template <typename S, typename T>
void erase_if(S& givenset, T firstele, T lastele,
              function<bool(T)> checker)
{
    while (firstele != lastele) {
        if (checker(firstele)) {
            firstele = givenset.erase(firstele);
        }
        else
            firstele++;
    }
}
int main()
{
    typedef set<string>::iterator setItr;
    // creating a string set and initializing with some
    // strings
    set<string> stringset = { "Hello", "this",       "is",
                              "this",  "BTechGeeks", "on" };
    // printing the set before removing strings
    cout << "Printing the set before removing : " << endl;
    for (auto val : stringset)
        cout << val << " ";
    cout << endl;
    // If the length of the string is greater than two, this
    // callback is triggered.
    function<bool(setItr)> lambda = [](setItr itr) -> bool {
        return itr->size() > 2;
    };
    // removing the string from stringset if length of it is
    // greater than 2
    erase_if<>(stringset, stringset.begin(),
               stringset.end(), lambda);

    // printing the set after removing strings
    cout << "Printing the set after removing :" << endl;
    for (auto val : stringset)
        cout << val << " ";
    cout << endl;
    return 0;
}

Output:

Printing the set before removing : 
BTechGeeks Hello is on this 
Printing the set after removing :
is on

Related Programs: