Получение случайного значения из массива JavaScript


794

Рассматривать:

var myArray = ['January', 'February', 'March'];    

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

Ответы:


1482

Это простой однострочник

const randomElement = array[Math.floor(Math.random() * array.length)];

пример

const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const randomMonth = months[Math.floor(Math.random() * months.length)];

console.log("random month =>", randomMonth);


9
@SapphireSun это правильно. Обратите внимание на Math.floor(Math.random(...))звонок, который округляется вниз.
ashes999

33
Ааа, я узнал что-то новое. Я обсуждал случай, когда он равен ТОЛЬКО 1, но, по-видимому (согласно W3Schools) Math.random находится между 0 включительно и 1 эксклюзивно. Виноват.
SapphireSun

13
Я могу ошибаться, но я помню, var rand = myArray[Math.random() * myArray.length>>0]что был немного быстрее
vrugtehagel

6
на всякий случай, если вы уже используете lodash, вы можете использовать _.sample (array)
Габриэль Матусевич

2
Я предпочитаю этот вариант:var rand = myArray[Math.random() * myArray.length | 0]
Николас

76

Если у вас уже есть подчеркивание или перевод текста, вы можете использовать их _.sample.

// will return one item randomly from the array
_.sample(['January', 'February', 'March']);

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

// will return two items randomly from the array using underscore
_.sample(['January', 'February', 'March'], 2);

или используйте _.sampleSizeметод в lodash:

// will return two items randomly from the array using lodash
_.sampleSize(['January', 'February', 'March'], 2);

При использовании машинописного текста: имейте в виду, что возвращаемый тип будет «string | undefined» вместо «string», учитывая массив строк.
Стефан Шильке

23

Метод прототипа

Если вы планируете много получать случайное значение, вы можете определить для него функцию.

Во-первых, поместите это в свой код где-нибудь:

Array.prototype.sample = function(){
  return this[Math.floor(Math.random()*this.length)];
}

Сейчас же:

[1,2,3,4].sample() //=> a random element

Код передан в общественное достояние в соответствии с условиями лицензии CC0 1.0 .


И это делает что?
Кен Шарп

3
@KenSharp позволяет вам вызывать .sample()любой массив, чтобы получить случайный элемент
Бен Обин

6
Следует избегать расширения собственных типов объектов. Я удалил свой ответ, видя, что за него проголосовали, но пропагандируя плохую практику. Более подробное обсуждение этого вопроса см., Например, stackoverflow.com/questions/14034180/… и eslint.org/docs/rules/no-extend-native
Маркус Амальтея Магнусон

20

~~намного быстрее, чем Math.Floor(), поэтому, когда дело доходит до оптимизации производительности при создании вывода с использованием элементов пользовательского интерфейса, ~~выигрывает игра. БОЛЬШЕ ИНФОРМАЦИИ

var rand = myArray[~~(Math.random() * myArray.length)];

Но если вы знаете, что в массиве будут миллионы элементов, вы, возможно, захотите пересмотреть Math.Floor()битовый оператор, поскольку битовый оператор ведет себя странно с большими числами. См. Пример ниже, объясненный с выходом. БОЛЬШЕ ИНФОРМАЦИИ

var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343

1
Ссылка мертва, однако интересный пост, и я буду использовать это больше, чем Math.floorсейчас :)
aabbccsmith

1
Использование оператора «bitwise not», хотя и быстрее, не так читабельно, поэтому вы должны выбрать, что для вас важнее
Maciej Urbański

16

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

Основываясь на ответе @Markus, мы можем добавить еще одну функцию-прототип:

Array.prototype.randomDiffElement = function(last) {
   if (this.length == 0) {
      return;
   } else if (this.length == 1) {
      return this[0];
   } else {
      var num = 0;
      do {
         num = Math.floor(Math.random() * this.length);
      } while (this[num] == last);
      return this[num];
   }
}

И реализовать так:

var myRandomDiffElement = myArray.randomDiffElement(lastRandomElement)

11

Если у вас есть фиксированные значения (например, список названий месяцев) и вы хотите однострочное решение

var result = ['January', 'February', 'March'][Math.floor(Math.random() * 3)]

Вторая часть массива - это операция доступа, как описано в разделе Почему [5,6,8,7] [1,2] = 8 в JavaScript?


2
Такой кодекс - плохая и вредная практика. Это никогда не должно использоваться в производстве. Он имеет низкую читаемость и имеет жестко закодированную длину массива. Человек, изменяющий ввод массива, может забыть редактировать длину, жестко закодированную в конце.
Чайка

@Seagull OP никогда не спрашивал о конкретной среде. Также этот комментарий не имеет смысла, так как его можно применить практически ко всем ответам на этот вопрос;)
IG Pascual

Но большинство людей приходят к этому вопросу из поиска Google и могут использовать решение в других сценариях, чем в оригинальном ОП.
Чайка

@Seagull Ха-ха, люди могут сами решать, какой подход использовать, я не являюсь часто задаваемым вопросом о чистоте кода!
И.Г. Паскуаль

10

Самая короткая версия:

var myArray = ['January', 'February', 'March']; 
var rand = myArray[(Math.random() * myArray.length) | 0]

Что делает | 0?
Кен Шарп

2
Это превратит Float в Int, так же, как Math.floor.
foxiris

4
@KenSharp | 0сам по себе является побитовой операцией, которая ничего не делает, но в плавающих элементах javascript перед любой побитовой операцией они преобразуются в целые . Так что это что-то вроде того, как на + ''самом деле ничего не делать, но можно использовать для преобразования вещей в строки.
овчарка

Это не то же самое, что и здесь, Math.floorно это правильно. Это оператор, поэтому он работает быстрее, чем Math.floorесли бы только потому, что в любой момент выполнения некоторый код может это сделать, Math.floor = someOtherFunctionи они не могут сделать то же самое для '|'. С другой стороны, что касается Math.floorи |быть другим, попробуйте Math.floor(-1.5)против -1.5 | 0. Кстати, вам не нужны скобки. |имеет очень низкий приоритет.
Ган

7

Если вы хотите записать его в одну строку, как решение Паскуаля, другое решение было бы написать его, используя функцию поиска ES6 (основываясь на том факте, что вероятность случайного выбора одного из nэлементов равна 1/n):

var item = ['A', 'B', 'C', 'D'].find((_, i, ar) => Math.random() < 1 / (ar.length - i));
console.log(item);

Используйте этот подход для целей тестирования, и если есть веская причина не сохранять массив только в отдельной переменной. В противном случае другие ответы ( floor(random()*lengthи использование отдельной функции) - ваш путь.


Очень оригинальное решение. Отличная работа! Кстати, единственное реальное и динамичное однострочное решение здесь.
Славик Мельцер

7

В Faker.js есть много утилит для генерации случайных тестовых данных. Это хороший вариант в контексте набора тестов:

const Faker = require('faker');
Faker.random.arrayElement(['January', 'February', 'March']);

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


8
Для такой простой проблемы, как эта, добавление зависимости для всей библиотеки не нужно и добавляет к раздуванию кода. Во всяком случае, вы можете порекомендовать реальный метод, из Fakerкоторого выбирается случайный элемент массива.
Pixxl

1
«Простая проблема», подобная этой, обычно решается библиотеками, которые обеспечивают простое решение проблемы, с которой уже столкнулись сотни людей. Эти библиотеки обычно надежны и хорошо отлажены и имеют дело с различными оговорками, которые мы не хотим повторно реализовывать. Как правило, я бы порекомендовал использовать библиотеку.
Smonff

Чем вам нужно просто скопировать этот метод из библиотеки и поместить его в файл утилит
Рик Бросс

Рекомендация о том, что библиотеки должны оцениваться по весу WRT, когда они отправляются в веб-браузер, является разумным советом, и я искренне согласен, что отправка Faker.js в браузер была бы нелепой. Однако в вопросе не упоминается, какая среда выполнения JS используется. Для среды выполнения на основе NodeJS более разумно использовать более тяжелые зависимости, как в случае, когда я использую Faker.js - в тестовых наборах Cucumber JS.
Натан

6

Редактирование прототипа Array может быть вредным. Здесь это простая функция, чтобы сделать работу.

function getArrayRandomElement (arr) {
  if (arr && arr.length) {
    return arr[Math.floor(Math.random() * arr.length)];
  }
  // The undefined will be returned if the empty array was passed
}

Применение:

// Example 1
var item = getArrayRandomElement(['January', 'February', 'March']);

// Example 2
var myArray = ['January', 'February', 'March'];
var item = getArrayRandomElement(myArray);

3

Рекурсивная, автономная функция, которая может возвращать любое количество элементов (идентично lodash.sampleSize ):

function getRandomElementsFromArray(array, numberOfRandomElementsToExtract = 1) {
    const elements = [];

    function getRandomElement(arr) {
        if (elements.length < numberOfRandomElementsToExtract) {
            const index = Math.floor(Math.random() * arr.length)
            const element = arr.splice(index, 1)[0];

            elements.push(element)

            return getRandomElement(arr)
        } else {
            return elements
        }
    }

    return getRandomElement([...array])
}


1

Это похоже, но более общее, чем решение @Jacob Relkin:

Это ES2015:

const randomChoice = arr => {
    const randIndex = Math.floor(Math.random() * arr.length);
    return arr[randIndex];
};

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


1

var item = myArray[Math.floor(Math.random()*myArray.length)];

или эквивалентная более короткая версия:

var item = myArray[(Math.random()*myArray.length)|0];

Образец кода:

var myArray = ['January', 'February', 'March'];    
var item = myArray[(Math.random()*myArray.length)|0];
console.log('item:', item);


1

Простая функция:

var myArray = ['January', 'February', 'March'];
function random(array) {
     return array[Math.floor(Math.random() * array.length)]
}
random(myArray);

ИЛИ

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();

ИЛИ

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();

Было бы лучше установить переменную myArrayy внутри вашей функции, чтобы не загрязнять глобальное пространство имен.
Нил Мейер

0

На мой взгляд, лучше, чем возиться с прототипами или объявлять их вовремя, я предпочитаю выставлять их в окне:

window.choice = function() {
  if (!this.length || this.length == 0) return;
  if (this.length == 1) return this[0];
  return this[Math.floor(Math.random()*this.length)];
}

Теперь в любом месте вашего приложения вы называете это как:

var rand = window.choice.call(array)

Таким образом, вы все еще можете использовать for(x in array)цикл правильно


1
Я не был здесь, когда кто-то отрицал это, и я не отрицал это, но я предполагаю, что раскрытие его окну в основном объявляет глобальную переменную. См .: stackoverflow.com/questions/2613310/…
Крис

1
Вы не должны когда-либо использовать for...inна массивах, или даже вообще. Вы рискуете пройти цепочку прототипов. Он также предназначен для всех свойств объекта, а не для всех индексов в массиве. Если вы хотите использовать итератор для массива, используйте for (var i = 0; i < foo.length; i++){}. Еще лучше, используйте что-то вроде Array.prototype.forEachэтого.
Роберт

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

0

Я нашел способ обойти сложности верхнего ответа, просто связав переменную rand с другой переменной, которая позволяет отображать это число внутри вызова myArray [] ;. Удалив созданный новый массив и поиграв с его сложностями, я нашел рабочее решение:

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

<script>

var myArray = ['January', 'February', 'March', 'April', 'May'];    

var rand = Math.floor(Math.random() * myArray.length);

var concat = myArray[rand];

function random() {
   document.getElementById("demo").innerHTML = (concat);
}
</script>

<button onClick="random();">
Working Random Array generator
</button>

</body>
</html>

Я запутался, почему concatздесь что-то меняется ... randomсамо по себе это не меняет, и больше ничего не вызывается более одного раза ...
BalinKingOfMoria Восстановление CMs

1
Это решение не совсем имеет смысла. Почему вы создаете переменную с именем concat?
superluminary

0

static generateMonth() { 
const theDate = ['January', 'February', 'March']; 
const randomNumber = Math.floor(Math.random()*3);
return theDate[randomNumber];
};

Вы устанавливаете постоянную переменную для массива, затем у вас есть другая константа, которая выбирает случайным образом между тремя объектами в массиве, а затем функция просто возвращает результаты.


-1

Общий способ получить случайный элемент (ы):

let some_array = ['Jan', 'Feb', 'Mar', 'Apr', 'May'];
let months = random_elems(some_array, 3);

console.log(months);

function random_elems(arr, count) {
  let len = arr.length;
  let lookup = {};
  let tmp = [];

  if (count > len)
    count = len;

  for (let i = 0; i < count; i++) {
    let index;
    do {
      index = ~~(Math.random() * len);
    } while (index in lookup);
    lookup[index] = null;
    tmp.push(arr[index]);
  }

  return tmp;
}


-1

randojs делает это немного более простым и читаемым:

console.log( rando(['January', 'February', 'March']).value );
<script src="https://randojs.com/1.0.0.js"></script>


1
Просто любопытно: почему отрицательные голоса?
Лепонцо

1
некоторые люди не являются поклонниками поиска в библиотеках кода, который они могли бы написать сами, даже если бы это делало вещи быстрее и читабельнее. если библиотека по какой-то причине закрывается, у вашего сайта теперь есть сбой. randojs не работает, но они не знают этого, потому что это не так хорошо известно, как библиотеки, такие как, например, jQuery
Аарон Плочарчик

-2

Вот пример того, как это сделать:

$scope.ctx.skills = data.result.skills;
    $scope.praiseTextArray = [
    "Hooray",
    "You\'re ready to move to a new skill", 
    "Yahoo! You completed a problem", 
    "You\'re doing great",  
    "You succeeded", 
    "That was a brave effort trying new problems", 
    "Your brain was working hard",
    "All your hard work is paying off",
    "Very nice job!, Let\'s see what you can do next",
    "Well done",
    "That was excellent work",
    "Awesome job",
    "You must feel good about doing such a great job",
    "Right on",
    "Great thinking",
    "Wonderful work",
    "You were right on top of that one",
    "Beautiful job",
    "Way to go",
    "Sensational effort"
  ];

  $scope.praiseTextWord = $scope.praiseTextArray[Math.floor(Math.random()*$scope.praiseTextArray.length)];


-3

Создайте одно случайное значение и передайте в массив

Пожалуйста, попробуйте следующий код ..

//For Search textbox random value
var myPlaceHolderArray = ['Hotels in New York...', 'Hotels in San Francisco...', 'Hotels Near Disney World...', 'Hotels in Atlanta...'];
var rand = Math.floor(Math.random() * myPlaceHolderArray.length);
var Placeholdervalue = myPlaceHolderArray[rand];

alert(Placeholdervalue);

5
Этот ответ использует то же решение, что и уже принятый ответ. Вам следует воздерживаться от добавления одного и того же решения дважды и вместо этого выдвигать только другие возможные альтернативы, которые могли бы внести больший вклад в разговор.
Pixxl
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.