如何随机化(洗牌)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()方法。首先,我们将库导入到脚本标签中。
语法
_.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 库会增加负载,因此将其作为最终选项。