So, I have an std::list<std::string> and I'm asking if there is a function or a trick to randomize the list.
Example:
first elem of the list : "Hello"
second elem of the list : "Stack"
third elem of the list : "Over"
fourth elem of the list : "Flow"
fifth elem of the list : "!!"
what I want is a function or a trick to get a random list like this for example :
first elem of the list : "Flow"
second elem of the list : "!!"
third elem of the list : "Hello"
fourth elem of the list : "Stack"
fifth elem of the list : "Over"
I think that You understand what I mean :)
If you want to keep your list as a list and even not modify it, but just provide a randomized "view" of it, then you can use a vector<reference_wrapper<const string>> and then shuffle the vector. This leaves the list intact, lets you see a shuffled version of it in the vector and doesn't need to copy all the strings.
For example:
#include <iostream>
#include <functional>
#include <iterator>
#include <algorithm>
#include <string>
#include <list>
#include <vector>
#include <random>
int main() {
std::list<std::string> l{"Hello", "Stack", "Over", "flow", "!!"};
std::vector<std::reference_wrapper<const std::string>> v(l.cbegin(), l.cend());
std::random_device rd;
std::mt19937 generator(rd());
std::shuffle(v.begin(), v.end(), generator);
std::cout << "Original list:\n";
std::copy(l.cbegin(), l.cend(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << "\nShuffled view:\n";
std::copy(v.cbegin(), v.cend(), std::ostream_iterator<std::string>(std::cout, " "));
}
Example output:
Original list:
Hello Stack Over flow !!
Shuffled view:
Hello Over !! Stack flow
Live example: https://ideone.com/a1LIyh
As people have mentioned, using a std::list in this circumstance is rather odd – really, you should be using something like std::vector, that will almost always do the same job better.
Nevertheless, for your case, the simplest 'non-solution' is to copy the list into a std::vector, use std::random_shuffle, and then copy it back again:
// get some data
std::list<std::string> data = getData();
// copy it into a vector and shuffle it
std::vector<std::string> temp(data.begin(), data.end());
std::random_shuffle(temp.begin(), temp.end());
// copy the (shuffled) vector back into the list
std::copy(temp.begin(), temp.end(), data.begin());
Admittedly, it isn't all that efficient due to copying the entire set of data in both directions, but for your purpose it should be fine. If you wanted, you might be able to make it more efficient by moving the data rather than using the std::vector constructor and std::copy, but I'll leave that up to you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With