




Мое любимое решение для перетасовки материалов - использовать сортировку N * log N и передавать ей предикат сортировки, который возвращает случайный результат. У него есть приятная функция, которую можно сделать с минимумом нового кода, используя строительные блоки, которые есть в большинстве языков даже в самых полосатых версиях.
С другой стороны, перемешивание - это всего лишь O (n) и всего около 5 строк кода, как показано в других ответах. (И это очень легко сделать только один раз с помощью дженериков.)
5 строк на 1 строку - это либо немного (всего 4 строки), либо много (80%). Также это проще запомнить.
И еще одно преимущество заключается в том, что сортировка может что-то использовать для получения хорошей производительности при свопах, поэтому при небольшом n это может быть быстрее.
Вы можете использовать алгоритм Перемешивание Фишера-Йетса, который работает в линейном времени.
Выдает неверные результаты - см. codinghorror.com/blog/archives/001015.html
Как насчет какого-нибудь Алгоритм тасования Кнута-Фишера-Йейтса?
for (int i = cards.Length - 1; i > 0; i--)
{
int n = rand.Next(i + 1);
Swap(ref cards[i], ref cards[n]);
}
Код взят из Кодирование ужасов. Это также рекомендуемая литература о том, как люди часто делают это неправильно.
Позвольте мне указать вам один способ НЕПРАВИЛЬНЫЙ сделать это, и, признаюсь, я использовал раньше и никогда не видел ошибки до этого сообщения в блоге:
Я бы создал новый список и заполнил его элементами, которые выбираются случайным образом и удаляются из исходного списка.
Посмотрите, как это сделать в 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();
Не совсем быстро, но чертовски круто.
Кого волнует производительность, если вы можете достать свою большую палку LINQ и показать другим, что вы лучше их? :-П
Просто помните, что идентификаторы GUID - это НЕТ, которые должны рассматриваться как случайные числа в криптографических целях. Они подходят для такого рода вещей, но не взаимозаменяемы.
Черт возьми! До тех пор, пока у нас не появится потребность делать это быстро.
Правила Linq. Я думаю, что вместо GUID я бы взял случайное число.
Это действительно должно быть частью стандартной библиотеки классов .net ...