Does C++ have an equivalent to python's set.pop()
? I've been looking at the documentation for unordered_set
s here, but there doesn't seem to be a way to 1. Access an arbitrary element, and/or 2. Access + remove an arbitrary element (popping).
You can either pop the first element
auto i = *set.begin();
set.erase(set.begin());
or if you're overly concerned about the implementation-defined internal ordering of the buckets (hint: you probably shouldn't be), you could remove a random element with something like
#include <unordered_set>
#include <iostream>
#include <random>
int main()
{
std::unordered_set<int> set{0, 1, 2, 3, 4, 5};
std::default_random_engine ran{std::random_device{}()};
auto it = set.begin();
std::advance(it, std::uniform_int_distribution<>{0, set.size() - 1}(ran));
std::cout << *it << '\n';
set.erase(it);
}
The above isn't particularly efficient however and you might be better off by filling a std::vector
, removing the duplicates, randomizing the order and then just pop_back
ing the elements.
#include <algorithm>
#include <vector>
#include <iostream>
#include <random>
int main()
{
std::vector<int> vec{0, 1, 2, 3, 3, 4, 5, 5};
std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
std::shuffle(
vec.begin(),
vec.end(),
std::default_random_engine{std::random_device{}()}
);
while (!vec.empty()) {
std::cout << vec.back() << '\n';
vec.pop_back();
}
}
(n.b. depending on your platform random_device
may not be a very good seed).