js 生成隨機陣列或者叫做洗牌演算法
阿新 • • 發佈:2019-01-01
我們假設有一個顏色陣列是這樣的
var arr = ["red", "green", "blue", "yellow", "brown", "violet"]。如果將其順序打亂,生成一個隨機的陣列。
這該如何做呢?
1.一種直觀的做法就是,隨機生成一個[0, arr.lebgth-1] 區間的隨機數
然後彈出(splice)一個數據,繼續生成.逐漸迭代即可 。這種方法最耗時
function randomArray(arr) { var arr = arr.slice(); // 返回一個副本,不改變原陣列,為了測試方便,新增的。其實可以不需要 var temp_result = []; var num; while(arr.length != 0) { num = Math.round(0 + (arr.length-1 -0)* Math.random()); if(temp_result.indexOf(arr[num]) == -1) { temp_result.push(arr[num]); } arr.splice(num, 1); } return temp_result; }
2.另外附加一種更為簡單的操作,執行時間排在第二位。
function anotherRandomArray(arr) {
var arr = arr.slice();
return arr.sort(function (left, right) {
return Math.random() > 0.5? -1 : 1;
});
}
有人說上面這種寫法,達不到隨機的目的,其實這種認識是不正確的,下面我們會寫一個測試函式來看一下是否符合平均分佈。
3. 效能最好的交換資料
function shuffleArray(arr) { var arr = arr.slice(); var len = arr.length; var temp, random_index; while(len != 0) { random_index = Math.round( 0 + (len-1-0) * Math.random()); temp = arr[random_index]; arr[random_index] = arr[len-1]; arr[len-1] = temp; --len; } return arr; }
給出一種測試函式。
function testRandom(color_arr, specific_color, func_name,count) { /* @color_arr: 顏色陣列 @specifi_color: 某種特定的yanse @func_name: 使用哪個洗牌函式 @count: 執行多少次 */ var start_time = new Date(); var result = {}; for(var i=0; i<count; ++i) { var color_arr = func_name(color_arr); var index = color_arr.indexOf(specific_color); if(index in result) { result[index]++; }else { result[index] = 1; } } console.log(new Date() - start_time); return result; } var color_arr = ["red", "green", "blue", "yellow", "brown", "violet"]; console.log(testRandom(color_arr, "green", randomArray,100000)); console.log(testRandom(color_arr, "green", anotherRandomArray,100000)); console.log(testRandom(color_arr, "green", shuffleArray,100000));
測試10W次的結果如下:
180ms 77ms 42ms
{0: 16807, 1: 16518, 2: 16867, 3: 16550, 4: 16654, 5: 16604}
{0: 16890, 1: 16536, 2: 16871, 3: 16847, 4: 16385, 5: 16471}
{0: 16586, 1: 16635, 2: 16597, 3: 16718, 4: 16764, 5: 16700}
很明顯第三種洗牌演算法是最優的,而且使用sort函式來洗牌也是可以達到平均分佈的。
參考文章如下: