Random Record. Alternative.

  • Thread starter Thread starter shapper
  • Start date Start date
S

shapper

Hello,

To get a random record I am using the following:

context.Slides.Where(s => s.Active == true).ToList().GetRandom();

Where GetRandom is as follows:

public static class CollectionExtensions {
private static Random random = new Random();

public static T GetRandom<T>(this IList<T> list) {
if (list.Count == 0) return default(T);
return list[random.Next(0, list.Count)];
}
}

Wouldn't make more sense to have:
context.Slides.Where(s => s.Active == true).Random();

And is this even possible?

Thank You,
Miguel
 
[...]
Wouldn't make more sense to have:
context.Slides.Where(s => s.Active == true).Random();

And is this even possible?

Sure, it's possible. Just extend IEnumerable<T> instead of IList<T>.

But I'd be more worried about the fact that you ignored my earlier
suggestion to use Skip() and Take(), rather than converting the entire
collection to a list. If you were caching the list and retrieving
multiple random elements, converting to a list first makes more sense.
But for a single random element, enumerating the entire collection and
creating a whole new collection object, just so you can get one element,
is wasteful.

Pete
 
But I'd be more worried about the fact that you ignored my earlier  
suggestion to use Skip() and Take(), rather than converting the entire  
collection to a list.

Probably because I got lost or I didn't understood how to implement
your suggestion. :-)

Something are not so obvious to me ... believe me. :-)

I have the following:

public static class CollectionExtensions {

private static Random random = new Random();

public static T Random<T>(this IEnumerable<T> target) {
int position = random.Next(target.Count<T>());
return target.ElementAt(position);
}

public static T Random<T>(this IEnumerable<T> target, int count) {
for(int i=0;i<count;++i) {
int position = random.Next(target.Count<T>());
yield return target.ElementAt(position);
}
}
}

Thank You,
Miguel
 
[...]
I have the following:

public static class CollectionExtensions {

private static Random random = new Random();

public static T Random<T>(this IEnumerable<T> target) {
int position = random.Next(target.Count<T>());
return target.ElementAt(position);
}

Actually, Enumerable.ElementAt() is just as good here. I hadn't confirmed
it before, but I've now verified that it does what you'd expect and only
enumerate the collection as far as necessary to get to the expected
element.
public static T Random<T>(this IEnumerable<T> target, int count) {
for(int i=0;i<count;++i) {
int position = random.Next(target.Count<T>());
yield return target.ElementAt(position);
}
}
}

If you don't care about performance, then the above is fine too (assuming
your fixed return type). However, do keep in mind that you are
enumerating the collection up to the desired random element for each
random element you select. Note also that the above does not "shuffle"
the collection; it could return the same element multiple times.

As I mentioned before, when you need to return more than one random
element, you may well be better off to go ahead and convert the collection
to a list, so that it can be accessed randomly rather than iteratively.

Pete
 
Back
Top