Каков наилучший способ случайного переупорядочивания списка элементов в с #?

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

Это действительно должно быть частью стандартной библиотеки классов .net ...

Pyrolistical 06.01.2009 22:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
1
385
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Мое любимое решение для перетасовки материалов - использовать сортировку N * log N и передавать ей предикат сортировки, который возвращает случайный результат. У него есть приятная функция, которую можно сделать с минимумом нового кода, используя строительные блоки, которые есть в большинстве языков даже в самых полосатых версиях.

С другой стороны, перемешивание - это всего лишь O (n) и всего около 5 строк кода, как показано в других ответах. (И это очень легко сделать только один раз с помощью дженериков.)

Jon Skeet 06.01.2009 23:09

5 строк на 1 строку - это либо немного (всего 4 строки), либо много (80%). Также это проще запомнить.

BCS 06.01.2009 23:15

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

BCS 06.01.2009 23:17

Вы можете использовать алгоритм Перемешивание Фишера-Йетса, который работает в линейном времени.

Выдает неверные результаты - см. codinghorror.com/blog/archives/001015.html

Gavin Miller 06.01.2009 22:57
Ответ принят как подходящий

Как насчет какого-нибудь Алгоритм тасования Кнута-Фишера-Йейтса?

for (int i = cards.Length - 1; i > 0; i--)
{
    int n = rand.Next(i + 1);
    Swap(ref cards[i], ref cards[n]);
}

Код взят из Кодирование ужасов. Это также рекомендуемая литература о том, как люди часто делают это неправильно.

Позвольте мне указать вам один способ НЕПРАВИЛЬНЫЙ сделать это, и, признаюсь, я использовал раньше и никогда не видел ошибки до этого сообщения в блоге:

http://www.codinghorror.com/blog/archives/001015.html

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

Посмотрите, как это сделать в Linq:

public class Employee
{
    public int Id
    {
        get;
        set;
    }
    public string Name
    {
        get;
        set;
    }
}

Заполните список:

    List<Employee> list = new List<Employee>();

    list.Add(new Employee { Id = 1, Name = "Davolio Nancy" });
    list.Add(new Employee { Id = 2, Name = "Fuller Andrew" });
    list.Add(new Employee { Id = 3, Name = "Leverling Janet" });
    list.Add(new Employee { Id = 4, Name = "Peacock Margaret" });
    list.Add(new Employee { Id = 5, Name = "Buchanan Steven" });
    list.Add(new Employee { Id = 6, Name = "Suyama Michael" });
    list.Add(new Employee { Id = 7, Name = "King Robert" });
    list.Add(new Employee { Id = 8, Name = "Callahan Laura" });
    list.Add(new Employee { Id = 9, Name = "Dodsworth Anne" });

Затем отсортируйте:

    list = list.OrderBy(emp => Guid.NewGuid()).ToList();

Кредит

Не совсем быстро, но чертовски круто.

user1228 06.01.2009 23:15

Кого волнует производительность, если вы можете достать свою большую палку LINQ и показать другим, что вы лучше их? :-П

BFree 06.01.2009 23:17

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

Clinton Pierce 06.01.2009 23:18

Черт возьми! До тех пор, пока у нас не появится потребность делать это быстро.

user1228 06.01.2009 23:19
msdn.microsoft.com/en-us/library/… использует класс, аналогичный приведенному в примере кода, для генерации криптографически случайного числа вместо использования NewGuid (). Нет ни слова о производительности по этому поводу, тем не менее.
user1228 06.01.2009 23:22

Правила Linq. Я думаю, что вместо GUID я бы взял случайное число.

Mark Maxham 06.01.2009 23:38

Попробуйте этот код здесь

Он использует IComparer.Compare

Будет хорошей практикой, если вы будете выполнять функцию с помощью дженерики

Другие вопросы по теме