Выборка с "Math.random" иногда выбирает дублирующиеся элементы из массива - PullRequest
1 голос
/ 03 апреля 2020

Я пытаюсь произвольно передать элементы голосового канала элементам в сообщении. но он снова выбирает того же человека. как я могу предотвратить это? также пользователь, как это, не зная разногласий. js ppl example = user = ["2222222", "21111112"]

let users = message.member.voiceChannel.members
.filter(y => y.user.id !== message.author.id)
.map(a => a.user.id);
for (var i = 0; i < num; i++) {
var user = users[Math.floor(Math.random() * num)];
console.log(user);
let adi = message.guild.members.get(user);
liste += "" + adi.displayName + " adlı kullanıcının rolü " + rol + "\n";
oyuncular += " <@" + adi.user.id + "> ";

}

Ответы [ 2 ]

2 голосов
/ 03 апреля 2020

Существует два вида методов случайного выбора: «бросок» и «сделка». Бросок может получить одно и то же значение более одного раза, как при броске в кости. Сделка получает другое значение, как при раздаче карт.

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

Допустим, вы заполнили свой массив users, и теперь вы хотите получить из него num значений. Для этого вы удалили каждый элемент из вашего массива по вашему выбору. Это работа для splice().

for (let i = 0; i < num; i++) {
  if (users.length <= 0) break
  const randex = Math.floor(Math.random() * users.length)
  const user = users.splice(randex, 1)[0]
  /* do what you want with this user */
}

Соединение - хороший выбор для этого; V8 Javascript Движок Разработчики приложили немало усилий, чтобы сделать его максимально эффективным.

Вы можете проверить это, вставив следующий код в консоль REPL в вашем браузере devtools.

(function deal (k, n) {
  function range1(i){return i?range1(i-1).concat(i):[]}
  const users = range1(n)
  for (let i = 0; i < k; i++) {
    if (users.length <= 0) break
    const randex = Math.floor(Math.random() * users.length)
    const user = users.splice(randex, 1)[0]
    console.log (user)
  }
})(7, 52)

Это упрощение алгоритма тасования Фишера-Йейтса (он же Кнут), упомянутого здесь . Этот алгоритм перемешивает все во входном массиве. Но в этом нет необходимости, если вам нужно выбрать только несколько элементов из более длинного массива.

0 голосов
/ 03 апреля 2020

Что такое 'num' в вашем примере?

Конечно, будет работать следующее:

var user = users[Math.floor(Math.random() * users.length)];
...