Подтвердить что ты не робот

Как получить случайный объект с помощью 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++;
}

Это лучший способ сделать это?

4b9b3361

Ответ 1

Как насчет:

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)];
}

Ответ 3

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

SelectedPost = q.OrderBy(qu => Guid.NewGuid()).First();

Ответ 4

var rand = new Random();
var selectedPost = q.Skip(rand.Next(0, q.Count())).Take(1).FirstOrDefault();

Оптимально, вы хотите, чтобы когда-либо только выполнялся запрос функции для одного значения, поэтому вы устанавливаете Skip/Take, чтобы перейти к порядковому номеру, совпадающему со случайным числом, которое вы генерируете (ограничено набором данных itemcount, поэтому проблема с отсутствующей строкой ограничение на основе MAX (pkey) не является проблемой), а затем выхватывает первый элемент в этой точке последовательности.

В SQL это то же самое, что запрос SELECT Count(*) FROM q, затем SELECT * FROM q LIMIT {0}, 1 где {0} - это rand.Next(0, count), что должно быть довольно эффективным.

Ответ 5

Общий метод расширения, основанный на принятом ответе (который не всегда пропускает первый и перечисляет только однократно):

 public static class EnumerableExtensions
    {
        public static T Random<T>(this IEnumerable<T> enumerable)
        {
            var r = new Random();
            var list = enumerable as IList<T> ?? enumerable.ToList();
            return list.ElementAt(r.Next(0, list.Count()));
        }
    }

Ответ 6

Поздно к вечеринке, но это высокий результат Google. Краткая версия может быть:

var rnd = new Random();
var SelectedPost = q.OrderBy(x => rnd.Next()).Take(1);

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

Ответ 7

Я отправляю ответ, потому что у меня недостаточно репутации для комментариев.

Мне нравится этот ответ:

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

Но ElementAt основано на нулевом значении, безусловно, начиная с 1 и переходя к Answers.Count(), вы собираетесь в конечном итоге потенциально выбросить диапазона, и вы никогда не получите первый объект.

Не будет ли

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

Лучше?

Ответ 8

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

Ответ 9

У меня есть таблица продуктов в базе данных, каждый раз, когда пользователь вводит одну деталь продукта, я хочу показать 10 похожих продуктов на странице ниже. И в каждом обновлении этот список должен быть изменен .it должен поступать случайным образом.

Linq выглядит так:

var products =
            DataContextFactory.GetDataContext()
                .Set<Product>()
                .Where(x =>x.Id!=id)
                .OrderBy(emp => Guid.NewGuid())
                .Take(10).ToList();

x.Id!=id 

это только для того, чтобы не отображать выбранный продукт.

Он отлично работает