tags:

views:

163

answers:

3
+1  Q: 

Random Linq Query

Hi guys,

how I can get a random row from a selection in my linq query?

I tried:

Bot bot = (from a in dc.Bot
           select a).OrderBy(x => Guid.NewGuid()).First();

But doesn't work, I ever get the same.

+6  A: 

I would use Skip

var query = from a in dc.Bot
            select a;

int random = new Random().Next(query.Count);

Bot bot = query.Skip(random).First();
Bob
+1. Sounds sensible.
RichardOD
+1 - very good idea. Combine this with an extension like Guffa has done, and that's the best of all worlds.
Shaul
@Shaul: As this method uses the query twice, it's not really well suited to make an extension out of.
Guffa
+3  A: 

Something like this might work:

var random = new Random();
var allBots = (from a in dc.Bot select a);

var randomAmountToSkip = random.NextInt(allBots.Count());
var anyBot = allBots.Skip(randomAmountToSkip).First()
Gamlor
Isn't that the same answer that Bob provided earlier?
Meta-Knight
I think this is the fasted gun in the west problem http://meta.stackoverflow.com/questions/9731/fastest-gun-in-the-west-problem
Bob
+2  A: 

I have an extension method for that in my archive:

static class IEnumerableExtensions {

   public static T PickRandomOne<T>(this IEnumerable<T> list, Random rnd) {
      T picked = default(T);
      int cnt = 0;
      foreach (T item in list) {
         if (rnd.Next(++cnt) == 0) {
            picked = item;
         }
      }
      return picked;
   }

}

Usage:

Random rnd = new Random();
Bot bot = (from a in dc.Bot select a).PickRandomOne(rnd);

The advantage of this method is that you don't need to know how many items there are beforehand, so you don't have to run the query twice.

Guffa
+1 - nice extension!
Shaul
Hang on - pls explain this: how does your foreach loop guarantee that you'll ever set the value of "picked"? And wouldn't this method inherently favor items toward the end of the enumeration, thus making it less random?
Shaul
@Shaul: `rnd.Next(1)` always returns 0, so the first item is always put in the ´picked` varaible. The second item has 50% chance to replace the first, and so on with falling probability throughout the collection, so there is no skew in the algorithm.
Guffa