从JavaScript数组中获取随机值

考虑:

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

如何使用JavaScript从这个数组中选择一个随机值?

908342 次浏览

这是一个简单的单行代码:

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

例如:

const months = ["January", "February", "March", "April", "May", "June", "July"];
const random = Math.floor(Math.random() * months.length);console.log(random, months[random]);

假设你想选择一个与上次不同的随机项目(不是真的随机,但仍然是一个常见的要求)…

/*** Return a random element from an array that is* different than `last` (as long as the array has > 1 items).* Return null if the array is empty.*/function getRandomDifferent(arr, last = undefined) {if (arr.length === 0) {return null;} else if (arr.length === 1) {return arr[0];} else {let num = 0;do {num = Math.floor(Math.random() * arr.length);} while (arr[num] === last);return arr[num];}}

像这样实现:

const arr = [1,2,3];const r1 = getRandomDifferent(arr);const r2 = getRandomDifferent(arr, r1); // r2 is different than r1.

在我看来,比起乱搞原型,或者及时声明它,我更喜欢将它暴露在窗口中:

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)循环

如果您有固定值(如月份名称列表)并且想要单行解决方案

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

数组的第二部分是访问操作,如为什么在JavaScript中[5,6,8,7][1,2]=8?所述

如果您的项目中已经包含强调豆沙,则可以使用#0

// 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);

或使用#0的方法:

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

您可以考虑在Array原型上定义一个函数,以创建一个返回随机元素的方法[].sample()

首先,要定义原型函数,请将此代码段放在您的代码中:

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

稍后,要从数组中采样一个随机元素,只需调用.sample()

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

我将这些代码片段发布到公共领域,根据CC0 1.0许可证的条款

这类似于,但比@Jacob Relkin的解决方案更通用:

这是ES2015:

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

该代码的工作原理是选择一个介于0和数组长度之间的随机数,然后返回该索引处的项目。

下面是一个如何做到这一点的例子:

$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)];

我已经找到了一种方法来解决顶部答案的复杂性,只需将变量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>

最短版本:

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

创建一个随机值并传递给数组

请尝试以下代码…

//For Search textbox random valuevar 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);

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);

如果你想把它写在一行上,就像Pascual的解决方案一样,另一种解决方案是使用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和使用单独的函数)是你的出路。

递归的独立函数,可以返回任意数量的项目(与lodash.sample尺寸相同):

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])}

Faker.js有许多用于生成随机测试数据的实用函数。在测试套件的上下文中,它是一个不错的选择:

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

正如评论者所提到的,您通常不应该在生产代码中使用这个库。

简单功能:

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();

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

您为数组设置一个常量变量,然后有另一个常量在数组中的三个对象之间随机选择,然后函数简单地返回结果。

~~Math.Floor()快得多,因此在使用UI元素生成输出时进行性能优化时,~~赢得了比赛。更多信息

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

但是如果你知道数组将有数百万个元素,那么你可能需要重新考虑按位运算符和Math.Floor()之间的关系,因为按位运算符对大数字的行为很奇怪。

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

编辑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 1var item = getArrayRandomElement(['January', 'February', 'March']);
// Example 2var myArray = ['January', 'February', 'March'];var item = getArrayRandomElement(myArray);

获取随机元素的通用方法:

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;}

要获取加密强随机项表单数组使用

let rndItem = a=> a[rnd()*a.length|0];let rnd = ()=> crypto.getRandomValues(new Uint32Array(1))[0]/2**32;
var myArray = ['January', 'February', 'March'];
console.log( rndItem(myArray) )

randojs使其更简单易读:

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

寻找一个真正的单行我来到这里:

['January', 'February', 'March'].reduce((a, c, i, o) => { return o[Math.floor(Math.random() * Math.floor(o.length))]; })

通过在数组原型上添加方法,可以轻松获取随机值。

在此示例中,您可以从数组中获取单个或多个随机值。

您可以通过单击代码片段按钮来运行测试代码。

Array.prototype.random = function(n){if(n&&n>1){const a = [];for(let i = 0;i<n;i++){a.push(this[Math.floor(Math.random()*this.length)]);}return a;} else {return this[Math.floor(Math.random()*this.length)];}}
const mySampleArray =  ['a','b','c','d','e','f','g','h'];
mySampleArray.random(); // return any random value etc. 'a', 'b'mySampleArray.random(3); //retun an array with random values etc: ['b','f','a'] , ['d','b','d']
alert(mySampleArray.random());alert(mySampleArray.random(3));

方法一:

  • 使用Math.random()函数获取(0-1,1之间的随机数唯一的)。
  • 将其乘以数组长度以获得数字之间(0-数组长度)。
  • 使用Math.floor()获取索引范围from(0到arrayLizth-1).

const arr=["foo","bar"];
arr[Math.floor(Math.random()*arr.length)]console.log

方法二:

  • 随机(a, b)方法用于生成(a到b,b独占)之间的数字。
  • 取底限值,将数字的范围从(1到arrayL的长度)。
  • 减去1以获得范围从(0到arrayLseth-1)的索引。

const arr=["foo","bar"];
arr[Math.floor(随机(1,5))-1];//console.log

如果您需要多次获取随机项目,那么显然您将使用函数。一种方法是使该函数成为Array.prototype的方法,但这通常会让您因篡改内置原型而被叫停。

但是,您可以将该方法添加到特定数组本身:

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

这样,您可以随心所欲地使用months.random(),而不会干扰泛型Array.prototype

与任何随机函数一样,你面临连续获得相同值的风险。如果你不想这样,你需要使用另一个属性跟踪以前的值:

months.random=function() {var random;while((random=this[Math.floor(Math.random()*this.length)]) == this.previous);this.previous=random;return random;};

如果你打算经常做这样的事情,并且你不想篡改Array.prototype,你可以这样做:

function randomValue() {return this[Math.floor(Math.random()*this.length)];}
var data = [ … ];var moreData = [ … ];
data.random=randomValue;moreData.random=randomValue;

我真的很惊讶没有人尝试使用本机随机值:

array[Date.now()%array.length]

它不适用于超过160000000000的数组长度,但我相信你永远不会像这样创建数组

UPD

就你的问题而言,如何从名为myArray(len=3)的数组中选择随机值,解决方案应该是:

myArray[Date.now()%myArray.length]

许多提供的解决方案都向特定数组添加了一个方法,这限制了它只能使用该数组,并且在TypeScript中也不起作用。这个TypeScript解决方案是类型安全和可重用的代码,适用于任何数组:

export function randChoice<T>(arr: Array<T>): T {return arr[Math.floor(Math.random() * arr.length)]}