ChatGPT解决这个技术问题 Extra ChatGPT

从 JavaScript 数组中获取随机值

考虑:

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

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


j
jakanz

这是一个简单的单行:

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

例如:

const 月 = [“一月”、“二月”、“三月”、“四月”、“五月”、“六月”、“七月”]; const random = Math.floor(Math.random() * months.length); console.log(随机,月[随机]);


@SapphireSun 这是正确的。注意 Math.floor(Math.random(...)) 调用,它向下取整。
啊,我学到了一些新东西。我正在讨论它等于 1 的情况,但显然(根据 W3Schools)Math.random 介于 0 和 1 之间。我的错。
我可能是错的,但我记得 var rand = myArray[Math.random() * myArray.length>>0] 稍微快一点
我更喜欢这个变体:var rand = myArray[Math.random() * myArray.length | 0]
为什么每个人都使用 Math.floor 而不是 Math.trunc
B
Brendan Nee

如果您的项目中已包含 underscorelodash,则可以使用 _.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);

或使用 lodash 中的 _.sampleSize 方法:

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

使用打字稿时:请注意,返回类型将是“字符串|未定义”而不是“字符串”给定一个字符串数组。
B
Ben Aubin

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


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

~~Math.Floor() 快得多,因此在使用 UI 元素生成输出时的性能优化方面,~~ 胜出。 MORE INFO

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

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

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

链接已经死了,但是有趣的帖子,我现在会使用这个超过 Math.floor :)
使用“按位非”运算符虽然速度更快,但可读性不高,因此您必须选择对您更重要的内容
双蒂尔达 - 有趣......我学到了一些新东西。
对于那些想了解它的含义的人来说,~ 是按位的 not,它将二进制数中的 10 反转。与所有按位运算符一样,它首先将数字转换为您真正想要的 32 位整数。使用 ~~ 将原始数据恢复为 32 位整数。
至于 Math.floor(),所有函数都有开销,包括存储和恢复原始状态。通常,优化编译器会寻找机会将代码复制到适当的位置以避免这种开销,但是对于 JavaScript 这样的动态语言,它更难预测。
A
AATHITH RAJENDRAN

最短的版本:

var myArray = ['一月','二月','三月']; var rand = myArray[(Math.random() * myArray.length) | 0] 控制台日志(兰德)


| 0 有什么作用?
它将 Float 转换为 Int,与 Math.floor 相同。
@KenSharp | 0 本身是一个不执行任何操作的按位运算,但在 javascript 中,浮点数是 converted to ints before any bitwise operation。所以这有点像 + '' 并没有真正做任何事情,但可以用来将事物转换为字符串。
它与 Math.floor 不同,但它是正确的做法。它是一个运算符,所以它比 Math.floor 快,因为在任何时候运行一些代码都可以做 Math.floor = someOtherFunction 而他们不能对 '|' 做同样的事情。另一方面,对于 Math.floor| 不同,请尝试 Math.floor(-1.5)-1.5 | 0。顺便说一句,你不需要括号。 | 的优先级很低。
C
CrazyTim

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

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

C
Community

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

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

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


这样的代码是一种不好的和有害的做法。它不应该在生产中使用。它的可读性低,并且具有硬编码的数组长度。更改数组输入的人可能会忘记编辑最后硬编码的长度。
@Seagull OP 从未要求特定环境。此外,此评论毫无意义,因为它几乎可以应用于此问题中的所有答案;)
但是大多数人从谷歌搜索到这个问题,并且可能在原始 OP 之外的其他场景中使用该解决方案。
@Seagull 哈哈人们可以自由决定使用哪种方法,我不是干净的代码指南常见问题解答!
我喜欢它的可读性,我自己也找到了相同的解决方案
S
Stephan

如果你想把它写在一行上,就像 Pascual 的解决方案一样,另一种解决方案是使用 ES6 的 find 函数来编写它(基于这样一个事实,从 n 个项目中随机选择一个项目的概率是 1/n):

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

将该方法用于测试目的,并且如果有充分的理由不将数组仅保存在单独的变量中。否则,其他答案(floor(random()*length 并使用单独的函数)是您的选择。


N
Nathan

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

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

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


对于像这样的简单问题,不需要为整个库添加依赖项,并且会增加代码膨胀。如果有的话,您可能会推荐来自 Faker 的实际方法,该方法选择一个随机数组元素。
像这样的“简单问题”通常由图书馆解决,这些图书馆为数百人已经不得不面对的问题提供简单的解决方案。这些库通常是健壮且经过良好调试的,并且可以处理我们不想重新实现的各种警告。这通常是我建议使用库的情况。
比你应该从库中复制一个方法并将它放在一个 utils 文件中
当库被运送到 Web 浏览器时,应该评估其成本/收益 WRT 页面重量的建议是合理的建议,我完全同意将 Faker.js 运送到浏览器是荒谬的。但是,该问题没有提到正在使用哪个 JS 运行时。对于基于 NodeJS 的运行时,较重的依赖项是完全合理的,我在 Cucumber JS 测试套件中使用 Faker.js 就是这种情况。
我正在研究已经使用 faker.js 的测试,所以这对我来说是一个有用的答案。
M
Manngo

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

S
Seagull

编辑数组原型可能是有害的。这是一个简单的功能来完成这项工作。

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

K
Kamil Kiełczewski

要获得 crypto-strong 随机项形式数组,请使用

让 rndItem = a=> a[rnd()*a.length|0];让 rnd = ()=> crypto.getRandomValues(new Uint32Array(1))[0]/2**32; var myArray = ['一月','二月','三月'];控制台日志(rndItem(myArray))


d
dwilt

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

M
Max Heiber

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

这是 ES2015:

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

该代码通过在 0 和数组长度之间选择一个随机数来工作,然后返回该索引处的项目。


P
Pavel P

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

或等效的较短版本:

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

示例代码:

var myArray = ['一月','二月','三月']; var item = myArray[(Math.random()*myArray.length)|0]; console.log('item:', item);


D
Dhakshith

简单功能:

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 变量,以免污染全局命名空间。
w
weisk

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

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


当有人反对它时,我不在这里,我也没有反对它,但我的猜测是,将它暴露给窗口基本上是在声明一个全局变量。请参阅:stackoverflow.com/questions/2613310/…
您不应该在数组上使用 for...in,甚至一般情况下。你冒着走原型链的风险。它也适用于对象的所有属性,而不是数组中的所有索引。如果要对数组使用迭代器,请使用 for (var i = 0; i < foo.length; i++){}。更好的是,改用 Array.prototype.forEach 之类的东西。
我不喜欢这个,因为它污染了全局范围。你可以说这可能是唯一存在的,但它会养成违反这种良好做法的习惯。
F
FaverosGema

我找到了解决最佳答案复杂性的方法,只需将变量 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 本身并没有改变它,而且没有其他任何东西被多次调用......
这个解决方案并不完全有意义。为什么要创建一个名为 concat 的变量?
N
Neil Meyer

静态 generateMonth() { const theDate = ['一月','二月','三月']; const randomNumber = Math.floor(Math.random()*3);返回日期[随机数]; };

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


b
blagus

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

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

K
Kamuran Sönecek

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

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

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

Array.prototype.random = function(n){ if(n&&n>1){ const a = []; for(让 i = 0;i


P
Pirate King

方法一:

使用 Math.random() 函数获取(0-1, 1 除外)之间的随机数。

将它乘以数组长度以获得(0-arrayLength)之间的数字。

使用 Math.floor() 获取范围从 (0 到 arrayLength-1) 的索引。

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

方法二:

random(a, b) 方法用于生成介于(a 到 b,b 除外)之间的数字。

取下限值以将数字范围从(1 到 arrayLength)。

减 1 得到从 (0 到 arrayLength-1) 的索引。

常量 arr = ["foo","bar"]; const randomPickedString=arr[Math.floor(random(1, 5))-1]; console.log(randomlyPickedString);


R
Rafael

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

let some_array = ['Jan', 'Feb', 'Mar', 'Apr', 'May'];让月 = random_elems(some_array, 3); console.log(月);函数 random_elems(arr, count) { 让 len = arr.length;让查找 = {};让 tmp = [];如果(计数 > 长度)计数 = 长度; for (let i = 0; i < count; i++) { 让索引;做 { index = ~~(Math.random() * len); } 而(查找中的索引);查找[索引] = null; tmp.push(arr[index]); } 返回时间; }


m
mech

以下是如何执行此操作的示例:

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

J
Jignesh Darji

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

请尝试以下代码..

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

此答案使用与已接受答案相同的解决方案。您应该避免两次添加相同的解决方案,而只提出可能对对话做出更多贡献的其他替代方案。
A
Aaron Plocharczyk

randojs 使它更简单易读:

console.log(rando(['一月', '二月', '三月']).value );


有些人不喜欢在库中寻找他们可以自己编写的代码,即使这会使事情变得更快、更易读。如果图书馆因某种原因出现故障,您的网站现在出现故障。 randojs 没有下降,但他们不知道,因为它不像 jQuery 这样的库那么出名
E
Egor

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

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

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

UPD

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

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

我没有对您投反对票,但我看不出您的解决方案与该问题有何关联。我认为其他人也不能。
所以..是的,它“有点”有效,但又不是真的。它之所以被否决,是因为 Date.now() 与随机性无关,并且确实具有相当的确定性。我知道在某些用例中它可能感觉足够“随机”
@nuts Date.now() 每次都返回不同的值,这样就无法确定 100% 的准确度,此外,如果数组大约有 3 个元素。
@EgorRandomize 这些日期值是高度确定的。那是随机的反义词。再说一遍:是的,作为用户,您会感觉到随机性,但这与实际随机性无关。 (顺便说一句:我什至没有投反对票^^)
@nuts 是的,我同意你的想法,但我怎样才能将我的问题标记为另一个观点?因为在这里我只能看到 Math.Rand 个已实现的解决方案,只要它是一个伪随机函数