如何随机化(洗牌)JavaScript数组?
在本教程中,我们将学习随机化或洗牌 JavaScript 数组的方法。
我们可以通过使用某些库或算法中现有的洗牌函数来实现这一点。
让我们继续讨论这个问题。
使用 Fisher-Yates 算法和解构赋值
在此,算法从最后一个索引迭代到第一个索引。在每次循环中,它都会交换数组值并创建有限序列的随机排列。
我们可以按照以下语法使用此算法。
语法
for (var i=arr.length – 1;i>0;i--) { var j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; }
这里,解构赋值语法用于在循环内交换两个变量的值。
算法
步骤 1 - 列出 1 到 N。
步骤 2 - 选择一个介于 1 和剩余值之间的随机值 x。
步骤 3 - 将从最后开始的第 x 个值放入新列表中,并从实际列表中删除第 x 个值。
步骤 4 - 重复步骤 2,直到列表中的所有值都被删除。
步骤 5 - 步骤 3 中的新列表是实际列表的随机排列。
示例
在此代码中,我们在一行代码中交换两个变量的值。根据 Fisher-Yates 算法,我们的程序会对输入数组进行洗牌并显示输出。
<html> <body> <p id = "data"></p> <p id="result"></p> <script> function fisherYatesRandomize(arr) { for (var i = arr.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; } var fshArray = [10, 20, 30, 40, 50, 60]; document.getElementById("data").innerHTML = "Original Array - " +fshArray document.getElementById("result").innerHTML = "Shuffled Array - " + fisherYatesRandomize(fshArray); </script> </body> </html>
使用 Drustenfield 洗牌算法
Drustenfield 算法是Fisher-Yates算法的优化版本。
该算法为每个数组索引选择一个随机值,并从下一个选择中排除此值。这与从一副牌中抽牌完全一样。此循环向后工作。因此,这里的效率是最佳的。此算法的运行时间为O(n)。
用户可以按照以下语法使用此算法。
语法
for (var i = arr.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = array[i]; array[i] = array[j]; array[j] = temp; }
在此,交换是在循环内借助新变量完成的。
算法
步骤 1 - 令数组长度为 len
步骤 2 - 循环遍历索引 len-1 和 1 的值。递减循环控制 lc。
步骤 3 - 从当前 lc 和 1 中选择一个随机值 n。
步骤 4 - 交换索引 n 和 lc 的值。因此,随机值会向下一个迭代索引移动。
步骤 5 - 继续步骤 2 和后续步骤,直到循环结束。
示例
在此示例中,我们将数组提供给循环。Math.random() 和一般交换在从最后一个索引到第一个索引的循环内工作。循环执行后返回洗牌后的数组。
<html> <body> <h3> Shuffle a JavaScript array using <i>Drustenfield shuffle algorithm</i> </h3> <p id="data"></p> <p id="result"></p> <script> function doShuffle(array) { for (var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = array[i]; array[i] = array[j]; array[j] = temp; } return array; } var drsArr = [100, 200, 300, 400, 500, 600]; document.getElementById("data").innerHTML = "Original Array - " + drsArr document.getElementById("result").innerHTML = "Shuffled Array - " + doShuffle(drsArr); document.getElementById("result").innerHTML = "Shuffled Array - " + doShuffle(drsArr); </script> <p> Note: You may get different shuffled array each time when you run the program </body> </html>
使用 Array sort() 方法
在这里,我们将讨论sort() 方法。sort() 方法依赖于 JavaScript 引擎。Math.random()的值在每次执行时可能为正或为负。这将返回 0 到 0.999 之间的值。Math.random() – 0.5 返回 -0.5 到 0.499 之间的值。
当 value1 和 value2 的排序结果大于 0 时,value1 将放在 value2 之前。这是逻辑。
sort 方法会修改原始数组。如果您需要原始数组的副本,可以使用下面给出的展开运算符语法。
语法
arr.sort(function(a, b) { return Math.random() - 0.5; }); //Arrow function syntax arr.sort(() => Math.random() - 0.5); //The spread operator syntax [...arr].sort(() => Math.random() - 0.5);
通常,数组的两个值会传递给 sort 函数,就像在第一个语法中一样。因为我们没有在函数内部使用它,所以我们可以省略参数。
示例
在此示例中,sort 方法使用 Math.random() – 0.5 逻辑以随机顺序对输入数组值进行排序。
<html> <body> <h3>Shuffle a JavaScript array using the <i>array sort()</i> method</h3> <p id="data"></p> <p id="result"></p> <script> let srtLst = [1, 2, 3, 4, 5, 6, 7]; document.getElementById("data").innerHTML = "Original Array - " + srtLst srtLst = srtLst.sort(() => Math.random() - 0.5); document.getElementById("result").innerHTML = "Shuffled array - " + srtLst; </script> <p>Note: You may get different shuffled array each time when you run the program</p> </body> </html>
使用 underscore.js/Lo-Dash 库
我们将看到如何在程序中实现此库方法。这里我们不需要任何算法。此库具有_.shuffle() 方法。首先,我们将在 script 标签中导入库。
语法
_.shuffle(arr);
在这里,输入数组将提供给此库的 shuffle 方法。
参数
arr - 输入数组
示例
在此程序中,我们添加了一个库文件。shuffle 方法处理我们的输入数组并显示洗牌后的数组。
<html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script> </head> <body> <h3> Shuffle a JavaScript array using <i>Underscore js library</i> </h3> <p id="libShuffOp"></p> <script> var libArray = ["Green", "Blue", "White"]; libResArray = _.shuffle(libArray); document.getElementById("libShuffOp").innerHTML = "Shuffled array - " + libResArray; </script> </body> </html>
本教程帮助我们学习了两种算法方法、数组排序方法和 JavaScript 库方法来随机化 JavaScript 数组。
Drustenfield 算法方法高效、快速且可靠。数组排序方法不可靠,因为没有明确的模式。Underscore.js 库会增加负载,因此最好将其作为最后的选择。