Выбор нескольких случайных элементов массива в JavaScript

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для извлечения случайных элементов из массива можно использовать метод перемешивания Фишера – Йетса и затем обрезать массив до нужной длины:

JS
Скопировать код
function getRandomElements(arr, n) {
  let w = arr.length, t, i;
  // Применяем алгоритм Фишера – Йетса
  while (w) {
    i = Math.floor(Math.random() * w--);
    t = arr[w];
    arr[w] = arr[i];
    arr[i] = t;
  }
  // Возвращаем первые n элементов
  return arr.slice(0, n);
}

// Пример использования:
const randomItems = getRandomElements([1, 2, 3, 4, 5, 6], 3);
console.log(randomItems);  // Пример результата: [4, 1, 5]

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

Кинга Идем в IT: пошаговый план для смены профессии

Эффективное перемешивание для больших массивов

При работе с большими массивами интенсивное перемешивание может снизить производительность. В этом случае целесообразно перемешивать элементы только до индекса n:

JS
Скопировать код
function efficientRandomElements(arr, count) {
  let result = new Array(count),
      len = arr.length,
      taken = new Array(len);
  if (count > len)
    throw new RangeError("efficientRandomElements: количество запрашиваемых элементов превышает их количество в массиве");
  while (count--) {
    let x = Math.floor(Math.random() * len);
    result[count] = arr[x in taken ? taken[x] : x];
    taken[x] = --len in taken ? taken[len] : len;
  }
  return result;
}

Компактный код с помощью lodash

Любители практичной и простой реализации, пользующиеся библиотекой lodash, могут выполнить выбор элементов следующим образом:

JS
Скопировать код
const _ = require('lodash');
let randomElems = _.sampleSize([1, 2, 3, 4, 5, 6], 3);

Гарантированное отсутствие дубликатов элементов

Если требуется набор уникальных элементов, использование Множества (Set) или метода _.sampleSize из lodash обеспечит уникальный выбор:

JS
Скопировать код
function uniqueFlowers(arr, n) {
  let resultSet = new Set();
  while (resultSet.size < n) {
    resultSet.add(arr[Math.floor(Math.random() * arr.length)]);
  }
  return Array.from(resultSet);
}

// Альтернативный подход — использование lodash:
let uniqueBlooms = _.sampleSize([1, 2, 3, 4, 5, 6], 3);

Будьте осторожны при запросе большого количества элементов

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

JS
Скопировать код
function cautionaryTale(arr, n) {
  if( n > arr.length ) { 
    console.warn("Запрошено больше элементов, чем доступно. Возвращаются все элементы массива.");
    return arr;
  }
  return getRandomElements(arr, n);
}

Визуализация

Можно представить процесс выбора случайных элементов как лотерею:

Исходный массив: [🔑, 🎩, 🐇, 🎓, 🎈, 📚]
Требуется выбрать: 3 случайных элемента

Процесс можно сравнить с тем, как если бы мы крутили барабан и вытаскивали 3 счастливых значка:

Запускаем... 🥁🌀
И выбираем: [🎓, 🐇, 🔑]

В коде это будет выглядеть так:

JS
Скопировать код
function getRandomElements(arr, count) {
  let shuffled = [...arr].sort(() => 0.5 – Math.random());
  return shuffled.slice(0, count);
}

Применение данной функции даст вам интересные и непредсказуемые результаты:

getRandomElements([🔑, 🎩, 🐇, 🎓, 🎈, 📚], 3)
// Возможный результат: [🎈, 🔑, 🎓]

Справедливый выбор при работе в условиях высокой нагрузки

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

Полезные материалы

  1. Math.random() — JavaScript | MDN — документация метода Math.random() на MDN.
  2. Get a random item from a JavaScript array — Stack Overflow — общение программистов об оптимальных способах извлечения случайных элементов из массива на Stack Overflow.
  3. Методы массивов — подробное описание разных методов обработки массивов, включая slice, на сайте learn.javascript.ru.
  4. how can I shuffle an array? — Stack Overflow — обсуждение разных способов перемешивания элементов массива на Stack Overflow.
  5. JavaScript — N random elements in array — 30 seconds of code — краткое руководство о том, как выбрать нескольких случайных элементов из массива на 30 seconds of code.
  6. Array.prototype.slice() — JavaScript | MDN — подробности метода Array.prototype.slice() на MDN.
Свежие материалы