Как получить элементы массива без повторения?

Как получить 5 элементов из массива без повторения?

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

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

Код ниже в настоящее время работает, но дает мне повторения. Как мне с этим поработать, чтобы исключить повторы?

(Вы можете увидеть это в действии здесь: https://davebirss.com/storydice/)

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

Заранее благодарим вас за помощь.

var diceRoll = ['${resourcesFolderName}/story_dice1.png',
        '${resourcesFolderName}/story_dice2.png',
        '${resourcesFolderName}/story_dice3.png',
        ...,
        '${resourcesFolderName}/story_dice51.png']

function choose(n, arr) {
    while (arr.length > n) {
        var del = Math.floor(Math.random() * arr.length);
        arr = arr.filter(function(item, i) {
            return i !== del;
        });
    }
    return arr;}

var result1 = [choose(1, diceRoll)];
var result2 = [choose(1, diceRoll)];
var result3 = [choose(1, diceRoll)];
var result4 = [choose(1, diceRoll)];
var result5 = [choose(1, diceRoll)];

hypeDocument.getElementById("dice1").innerHTML = "<img src='"+result1+" 'height='125' width='125'>";
hypeDocument.getElementById("dice2").innerHTML = "<img src='"+result2+" 'height='125' width='125'>";
hypeDocument.getElementById("dice3").innerHTML = "<img src='"+result3+" 'height='125' width='125'>";
hypeDocument.getElementById("dice4").innerHTML = "<img src='"+result4+" 'height='125' width='125'>";
hypeDocument.getElementById("dice5").innerHTML = "<img src='"+result5+" 'height='125' width='125'>";

Обновлять

Спасибо за вашу помощь. Я уверен, что все ответы были отличными, но фрагмент из U25lYWt5IEJhc3RhcmQg — это код, который мне удалось успешно внедрить. Для протокола, вот как я это сделал:

const rollTheDice = (arr, n) => {
  const randomN = [];
  while(randomN.length < n){
    const randomIndex = Math.floor(Math.random()*arr.length);
    randomN.push(arr[randomIndex]);
    arr.splice(randomIndex, 1);
  }
  return randomN;}

var result1 = (rollTheDice(images,1)); 
var result2 = (rollTheDice(images,1));
var result3 = (rollTheDice(images,1));
var result4 = (rollTheDice(images,1)); 
var result5 = (rollTheDice(images,1));

Я неоднократно перезагружала страницу и пока не видела повторов. Идеально!

1. сделать копию массива diceRoll.

pRmdk 30.05.2019 10:43

Возможный дубликат Генерация неповторяющихся случайных чисел в JS

sstruct 30.05.2019 11:05
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
2
151
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

  1. Сделайте копию массива diceRoll (diceRollCopy).
  2. Используйте новый массив (diceRollCopy) в качестве аргумента метода выбора.
  3. Всякий раз, когда вы получаете результат с использованием метода выбора удалить этот результат из массива копирования (DiceRollCopy).
  4. Вам нужно будет сбросить diceRollCopy на diceRoll после доступа к каждому набору результатов.

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

var length = 51,  // your count of items
    indices = [], // the result set with indices
    count = 5,    // the amount of wanted indices
    random;       // guess what?
    
while (indices.length < count) {                 // check length
    random = Math.floor(Math.random() * length); // get random value
    if (indices.includes(random)) continue;      // continue if already selected
    indices.push(random);                        // if not take it
}

console.info(indices);

Если ваш count достаточно мал по сравнению с length, существует высокая вероятность повторения Math.random() результатов и последующего continue, что является пустой тратой времени.

Yevgen Gorbunkov 30.05.2019 12:15

Скопируйте его, затем перетасуйте копию и каждый раз удаляйте первый элемент из массива:

const copy = [...diceRoll].sort(e => 0.5 - Math.random());

И в вашей функции выбора:

const chosen = copy.shift();
Ответ принят как подходящий

Думаю, самое сложное здесь — не тратить производительность впустую, ограничивая возможные варианты теми, которые ранее не были выбраны:

const images = ['a','b','c','d','e','f'];

const rollTheDice = (arr, n) => {
  const randomN = [];
  while(randomN.length < n){
    const randomIndex = Math.floor(Math.random()*arr.length);
    randomN.push(arr[randomIndex]);
    arr.splice(randomIndex, 1);
  }
  return randomN;
}

console.info(rollTheDice(images, 5));

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

Dave Birss 30.05.2019 18:20

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

var array = [1, 2, 3, 4, 5, 6];

/**
 * uniqGet
 * @param {*} array source array
 * @param {*} num how many elements to get
 */
function uniqGet(array, num) {
  if (array.length < num) {
    throw new Error("num should less than options");
  }
  let res = [];
  while (num > 0) {
    let index = Math.floor(Math.random() * array.length);
    res.push(array[index]);
    array.splice(index, 1);
    num--;
  }
  return res;
}

let result = uniqGet(array, 3); // [x, y, z]

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