I have a vector from struct Student
struct Student
::
struct Student{
string name;
float x;
float y;
bool dropped;
};
std::vector<Student> students;
I am looking for a way to randomly pick a vector item in which a special property (in this case dropped
value) is true
what is the most efficient way to do so?
CodePudding user response:
You could create a helper function that first collects iterators to all elements matching a unary predicate and then selects one of those at random.
It could look like this:
#include <random>
std::mt19937& prng() {
static std::mt19937 instance(std::random_device{}());
return instance;
}
template <class It, class UnaryPredicate>
It get_random(It first, It last, UnaryPredicate&& pred) {
if (first == last) return last; // empty range
std::vector<It> iters; // to store iterators to elements matching pred
for (; first != last; first) {
if (pred(*first)) iters.push_back(first); // matching pred, store it
}
// create a uniform integer distribution for [0, iters.size())
std::uniform_int_distribution<size_t> dist(0, iters.size() - 1);
// select a random iterator and return it:
return iters[dist(prng())];
}
It would then be used like this:
auto it = get_random(students.begin(), students.end(),
[](Student& s) { return s.dropped; });
std::cout << "picked " << it->name << '\n';