从 JavaScript 数组中获取随机值

IT技术 javascript random
2020-12-24 16:42:46

考虑:

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

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

6个回答

这是一个简单的单行:

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

啊,我学到了新东西。我正在讨论它等于 1 的情况,但显然(根据 W3Schools)Math.random 介于 0 和 1 之间。我的错。
2021-02-19 16:42:46
你的答案总是给出第一个数组?它没有给出随机值
2021-02-25 16:42:46
@SapphireSun 这是正确的。注意Math.floor(Math.random(...))调用,它向下舍入。
2021-02-27 16:42:46
我更喜欢这个变体: var rand = myArray[Math.random() * myArray.length | 0]
2021-03-01 16:42:46
我可能是错的,但我记得var rand = myArray[Math.random() * myArray.length>>0]稍微快一点
2021-03-08 16:42:46

如果您的项目中已经包含下划线lodash,则可以使用_.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);
使用typescript时:请注意,给定字符串数组时,返回类型将是“string | undefined”而不是“string”。
2021-02-24 16:42:46

您可以考虑在 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 许可条款将这些代码片段发布到公共领域

应避免扩展本机对象类型。我已经删除了我的答案,看到它被点赞了很多,但促进了不好的做法。有关此问题的更多讨论,请参见例如stackoverflow.com/questions/14034180/...eslint.org/docs/rules/no-extend-native
2021-02-19 16:42:46
@MarkusAmaltheaMagnuson 这是一个很好的观点。然而,在原型上定义自定义方法不一定是一个问题,特别是如果在库代码之外谨慎地这样做的话。原型提供了一个非常漂亮的替代解决方案(在我的主观看来)并且暴露了语言中有时被忽视但有趣的部分,至少在谨慎使用时是这样。对于几乎所有应用程序代码,这都不会导致问题,因此归结为品味问题。
2021-02-25 16:42:46
这有什么作用?
2021-02-27 16:42:46
@KenSharp 它允许您调用.sample()任何数组来获取随机项目
2021-03-02 16:42:46

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

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

但是,如果您知道数组将有数百万个元素,那么您可能需要重新考虑按位运算符 和 之间的关系Math.Floor(),因为按位运算符在处理大数时表现得很奇怪。请参阅下面的输出示例。

var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343
使用“按位非”运算符虽然速度更快,但可读性较差,因此您必须选择对您更重要的内容
2021-02-25 16:42:46
链接已死,但是帖子很有趣,我将比Math.floor现在更多地使用它:)
2021-02-27 16:42:46
double tilda - 有趣...我学到了一些新东西。
2021-02-28 16:42:46
对于那些想了解它意味着什么的人来说,~是一个按位not,它将1s 和0s反转为二进制数。与所有按位运算符一样,它首先将数字转换为 32 位整数,这正是您真正想要的。使用~~将原始恢复为 32 位整数。
2021-03-07 16:42:46
至于Math.floor(),所有函数都有开销,包括存储和恢复原始状态。通常,优化编译器会寻找机会将代码复制到位以避免这种开销,但是,对于诸如 JavaScript 之类的动态语言,更难预测。
2021-03-09 16:42:46

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

/**
 * 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;
  } 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.