Как получить Случайное использование Объекта Linq

Я пытаюсь получить случайный объект в linq. Вот то, как я сделал.

//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++;
}

Действительно ли это - лучший способ сделать это?

28
задан abatishchev 28 January 2012 в 20:28
поделиться

4 ответа

Как насчет:

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

Дополнительная литература:

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

Случайный элемент во всем вводе

Чтобы сделать все элементы кандидатами в случайный выбор, вам нужно изменить ввод на r.Next :

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

@Zidad добавляет полезный метод расширения к получить случайный элемент по всем элементам в последовательности:

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)];
}
39
ответ дан 28 November 2019 в 02:45
поделиться

Используйте тасование Фишера-Йетса-Дюрстенфельда .

(Вы можете использовать вспомогательный метод / метод расширения, чтобы перетасовать вашу IEnumerable последовательность . В качестве альтернативы, если вы использовали IList вы можете выполнить перемешивание на месте , если хотите.)

9
ответ дан 28 November 2019 в 02:45
поделиться

Еще один странный подход (не самый эффективный для больших наборов данных):

SelectedPost = q.OrderBy(qu => Guid.NewGuid()).First();
8
ответ дан 28 November 2019 в 02:45
поделиться

Получение всех ответов и их зацикливание - не самый эффективный способ, поскольку вы перемещаете большое количество данных из базы данных. Если вы используете целочисленный первичный ключ, который автоматически увеличивается, вы должны получить максимальное значение вашего первичного ключа, а затем найти случайное целое число в этом диапазоне. Затем напрямую получите единственный ответ на основе первичного ключа, полученного из случайной функции.

1
ответ дан 28 November 2019 в 02:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: