views:

86

answers:

3

I have a scenario where I have a list of classes, and I want to mix up the order. For example:

private List<Question> myQuestions = new List<Question>();

So, given that this is now populated with a set of data, I want to mix up the order. My first thought was to create a collection of integers numbered from 1 to myQuestions.Count, assign one at random to each question and then loop through them in order; however, I can’t seem to find a suitable collection type to use for this. An example of what I mean would be something like this:

for (int i = 0; i <= myQuestions.Count -1; i++) 
    tempCollection[i] = myQuestions[rnd.Next(myQuestions.Count-1)];

But I’m not sure what tempCollection should be – it just needs to be a single value that I can remove as I use it. Does anyone have any suggestions as to which type to use, or of a better way to do this?

+3  A: 

I suggest you copy the results into a new List<Question> and then shuffle that list.

However, I would use a Fisher-Yates shuffle rather than the one you've given here. There are plenty of C# examples of that on this site.

For example, you might do:

// Don't create a new instance of Random each time. That's a detail
// for another question though.
Random rng = GetAppropriateRandomInstanceForThread();

List<Question> shuffled = new List<Question>(myQuestions);
for (int i = shuffled.Count - 1; i > 0; i--)
{
    // Swap element "i" with a random earlier element it (or itself)
    int swapIndex = rng.Next(i + 1);
    Question tmp = shuffled[i];
    shuffled[i] = shuffled[swapIndex];
    shuffled[swapIndex] = tmp;
}
Jon Skeet
Isn't it shuffled.Count()?
pm_2
@pm_2: It should actually be `shuffled.Count - 1` - it's fine to use the property. But yes, it shouldn't be Length. Will fix.
Jon Skeet
A: 

temp Collection should be same type as myQuestions.

I would also suggest a change in your code:

for (int i = 0; i <= myQuestions.Count -1; i++)  

to

for (int i = 0; i < myQuestions.Count; i++)  

Does the same thing, but this is how most programers do it so it will make your code simpler to read.

EKS
+1  A: 

You could use Linq and order by a random value:

List<string> items = new List<string>(); 
items.Add("Foo");
items.Add("Bar");
items.Add("Baz");

foreach (string item in items.OrderBy(c => Guid.NewGuid()))
{
    Console.WriteLine(item);
}
Daniel Renshaw