Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a Random Object using Linq

Tags:

c#

.net

random

linq

I am trying to get a random object within linq. Here is how I did.

//get all the answers
var Answers = q.Skip(1).Take(int.MaxValue);
//get the random number by the number of answers
int intRandomAnswer = r.Next(1, Answers.Count());
int count = 0;

//locate the answer
foreach(var Answer in Answers)
{
    if (count == intRandomAnswer)
    {
        SelectedPost = Answer;
        break;
    }
    count++;
}

Is this the best way to do this?

like image 566
Luke101 Avatar asked Jul 04 '10 04:07

Luke101


3 Answers

What about:

SelectedPost = q.ElementAt(r.Next(1, Answers.Count()));

Further reading:

The comments below make good contributions to closely related questions, and I'll include them here, since as @Rouby points out, people searching for an answer to these may find this answer and it won't be correct in those cases.

Random Element Across Entire Input

To make all elements a candidate in the random selection, you need to change the input to r.Next:

SelectedPost = Answers.ElementAt(r.Next(0, Answers.Count()));

@Zidad adds a helpful extension method to get random element over all elements in the sequence:

public static T Random<T>(this IEnumerable<T> enumerable)
{
    if (enumerable == null)
    {
         throw new ArgumentNullException(nameof(enumerable));
    }

    // note: creating a Random instance each call may not be correct for you,
    // consider a thread-safe static instance
    var r = new Random();  
    var list = enumerable as IList<T> ?? enumerable.ToList(); 
    return list.Count == 0 ? default(T) : list[r.Next(0, list.Count)];
}
like image 51
codekaizen Avatar answered Sep 20 '22 06:09

codekaizen


Use a Fisher-Yates-Durstenfeld shuffle.

(You could use a helper/extension method to shuffle your IEnumerable<T> sequence. Alternatively, if you were using an IList<T> you could perform an in-place shuffle, if you prefer.)

like image 37
LukeH Avatar answered Sep 22 '22 06:09

LukeH


Another wacky approach (not the most efficient for larger data sets):

SelectedPost = q.OrderBy(qu => Guid.NewGuid()).First();
like image 30
BFree Avatar answered Sep 18 '22 06:09

BFree