从JavaScript数组中获取随机值

1233

考虑以下内容:

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

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

28个回答

8

修改数组原型可能会有害。这里提供了一个简单的函数来完成这个工作。

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

7

如果需要多次获取随机项,则显然需要使用函数。一种方法是将该函数作为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;

5
获取数组中的crypto-strong个随机项使用:

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


4

递归的、独立的函数,可以返回任意数量的项目(与 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])
}

2

简单函数:

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

最好将myArray变量设置在函数内部,以避免污染全局命名空间。 - Neil Meyer

2

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

这是ES2015:

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

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

2

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


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 本身并没有改变它,也没有其他东西被调用超过一次... - Joshua Grosso Reinstate CMs
1
这个解决方案并不完全合理。为什么要创建一个叫做 concat 的变量? - superluminary

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
我在任何人投反对票的时候都不在这里,而且我也没有投反对票,但我猜测将其暴露给窗口实际上就是声明了一个全局变量。参见:https://dev59.com/J3E85IYBdhLWcg3wyGp_ - Chris
1
你不应该在数组上使用for...in,甚至一般情况下也不应该使用。这样做会有遍历原型链的风险。它也是为对象的所有属性而设计的,而不是数组中的所有索引。如果你想在数组上使用迭代器,请使用for (var i = 0; i < foo.length; i++){}。更好的方法是使用类似于Array.prototype.forEach的东西。 - Robert
1
我不喜欢这样做,因为它会污染全局作用域。你可以说这可能是唯一的存在方式,但这会养成违反良好实践的习惯。 - Jekk

0

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接