Fisher Yates Shuffle, но с использованием функций массива Javascript
Я смотрел на предложения случайного выбора Фишера Йейтса на StackOverflow после исключения
arr.sort(v => Math.random() - 0.5)
из-за отсутствия случайности в последнем.
Функции Фишера Йейтса выглядят нормально, но используются в циклах while и т. Д. В качестве альтернативы, функции массива javascript (отображение, сокращение и т. Д.) Имеют очевидную проблему продвижения вперед, поэтому вам по-прежнему требуется доступ к длине массива, чтобы внедрить его ( что явно отнимает немного времени).
Итак, я написал свой собственный Фишер Йейтс, используя сокращение.
Я хотел это
Измените исходный массив, как это делает sort.
Верните исходный массив, чтобы я мог поместить его в начало цепочки функций массива, например
let myarr = [1, 2, 3, 4, 5]; let newARR = fyRandArr(myarr).filter(v => v !== 3);
Последняя итерация сокращения не требует каких-либо действий, потому что этот элемент уже случайным образом находится в позиции.
Моя функция работает и делает все, что указано выше.
Я программист-любитель, поэтому не уверен, что это считается хорошо написанным. Мне не у кого спросить. как это может быть улучшено?
const fyRandArr = arr =>
arr.reduce((A, v, i, a) => {
let r;
return i === A.lM1 ? a : (r = i + Math.floor(Math.random() * (A.l - i)), [a[i], a[r]] = [a[r], a[i]], A);
}, {l: arr.length, lM1: arr.length -1});
Очевидно, что если вам нужна чистая функция, то есть создание нового массива в случайном порядке, вы можете просто извлечь бит уменьшения и не беспокоиться о
fyRandArr
.
1 ответ
Для полноты картины в codereview установлено следующее:
- оператор запятой не нравится
- аккумуляторы разных типов не одобряются
- постоянная передача длины в накопитель объектов более «дорогостоящая», чем вычисление длины на каждой итерации.
При этом я записал следующее:
const fyRandArr = arr =>
arr.reduce((a, v, i) => {
let r, l = a.length;
[a[i], a[r = (i + Math.random() * (l - i)) | 0]] = [a[r], a[i]];
return a;
}, arr);
или
const fyRandArr = arr => {
arr.map((v, i, a) => {
let r, l = a.length;
[a[i], a[r = (i + Math.random() * (l - i)) | 0]] = [a[r], a[i]];
return a[i];
});
return arr;
};