user2862542
user2862542

Reputation: 205

Get X random elements from table in database using Linq or lambda in C#

I have a database with x amount users and I want to randomly get all the users and then write like 50 users out on my site. Right now I'm only using .take(50) and retrieves the latest 50 users. I want it to shuffle 50 random from whole table, Any ideas?

This is what my code looks like now:

userList = userList.OrderBy(user => -user.ID).Take(userCount).ToList();

NOTE: userlist is my list of all users. and as you can see I'm at the moment using lambda with a variable called userCount where I say how many users to list out!

Upvotes: 12

Views: 9098

Answers (5)

Dmitresky
Dmitresky

Reputation: 576

Extension Without Random

public static class MyExtensions
{
    public static IEnumerable<T> GetRandomItems<T>(this IEnumerable<T> source, Int32 count)
    {
        return source.OrderBy(s => Guid.NewGuid()).Take(count);
    }
}

And now you can

userList = userList.GetRandomItems().ToList();

Upvotes: 0

jwize
jwize

Reputation: 4165

Assuming you have an Id primary key column in your entity I would recommend to use the following query or you will be bringing down a lot of data for no reason.

var rnd = new Random();

// Get the employeeIds.
var employeeIds = EmployeeService.Data()
    .Select(e => e.Id)
    .ToList();

// Choose n number of random employeeIds.
var randomEmployeeIds = employeeIds
    .OrderBy(id => rnd.Next())
    .Take(x);

// Get random employees.
var employees = EmployeeService.Data().Where(emp => randomEmployeeIds.Contains(emp.Id));

Upvotes: 0

Matthew Steeples
Matthew Steeples

Reputation: 8078

There are 2 ways of doing this depending on how many users are in your system

1.

List<int> ids = new List<int>(50);
int total = userList.Count();
Random r = new Random();
while (ids.Count() < 50)
{
    var next = r.Next(total);
    if (!ids.Contains(next))
        ids.Add(next);
}
var users = userList.Where(a => ids.Contains(a.ID));

2.

MikeSW beat me to that one

Difference between the options is that 1) involves 2 queries queries to the database and 2) involves loading all of the users from the database just to load 50 of them. It's up to you which is a better way of doing it.

Upvotes: 0

Matten
Matten

Reputation: 17603

When it is okay to load all users and then take 50 of them, you can use a while loop like this:

List<object> randomUsers = new List<User>();
Random r = new Random();
while (randomUsers.Count < 50)
{
    userList
      // skip previously selected users
      .Except(randomUsers)
      // random number to skip a random amount of users
      .Skip(r.Next(0, userList.Count() - 1 - randomUsers.Count))
      // and then take the next one
      .First();
}

Upvotes: 0

MikeSW
MikeSW

Reputation: 16368

Try this

Random rnd = new Random();
userList = userList.OrderBy(user => rnd.Next()).Take(usercount).ToList();

Upvotes: 28

Related Questions