2009-11-27 2 views
2

Как я могу получить случайную строку из выделения в моем запросе linq?Случайный запрос Linq

Я пробовал:

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

Но не работает, я когда-нибудь то же самое.

ответ

4

Что-то, как это может работать:

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() 
+0

Разве это не тот самый ответ, который Боб предоставил ранее? –

+0

Я думаю, что это голодание в западной проблеме. Http://meta.stackexchange.com/questions/9731/fastest-gun-in-the-west-problem – Bob

8

Я хотел бы использовать Skip

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

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

Bot bot = query.Skip(random).First(); 
+0

+1. Звучит разумно. – RichardOD

+0

+1 - очень хорошая идея. Объедините это с расширением, как это сделал Гуффа, и это лучший из всех миров. –

+0

@Shaul: поскольку этот метод дважды использует запрос, он не очень хорошо подходит для создания расширения. – Guffa

2

У меня есть метод расширения для этого 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; 
    } 

}  

Использование:

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

Преимущество этого метода заключается в том, что вам не нужно знать, сколько предметов есть заблаговременно, поэтому вам не нужно дважды запускать запрос.

+0

+1 - приятное расширение! –

+0

Hang on - pls объясняют это: как ваш цикл foreach гарантирует, что вы когда-либо установили значение «выбрано»? И не будет ли этот метод по своей сути способствовать позициям в конце перечисления, что делает его менее случайным? –

+0

@Shaul: 'rnd.Next (1)' всегда возвращает 0, поэтому первый элемент всегда помещается в'picked' varaible. Второй элемент имеет 50% -ный шанс заменить первый и т. Д. С вероятностью падения во всей коллекции, поэтому в алгоритме нет искажений. – Guffa

Смежные вопросы