2016-06-28

JS: 如何打亂陣列順序?

如何打亂 javascript 中的陣列順序?

結論:

var ary = ['i', 'am', 'first'];
var newAry = ary.sort(function() {
    return Math.random() - 0.5
});
console.log(newAry);

廢話:

通常會嘮叨你整齊這件事的通常是老媽, 老婆或 老闆. 你說還有…, 但我不敢寫
關於寫程式這件事, 或多或少會產生強迫症式的潔癖. 因為, 寫程式的你看程式碼的時間絕對比看上面三老的時間還長.
但有時候, 我們不想要太整齊. 例如: 要產生無意義的測試資料(內容), 隨便說一些假話或隱藏某些東西時.

正文:

Javascript 的原生 Class 不多, Array 剛好是一個.
Array 這個 Class 的原生 Method 也不多, sort 剛好是一個.
但不是說要打亂順序, 怎麼又用排序的方法? 這是因為sort可以接受一個比較函式作為參數. 這個比較函式接受兩個參數, 且必須傳回一個負數, 零或正數作為比較結果. 利用比較函式比較兩個參數 a 和 b, 在各種可能情形需要傳回的值, 如下
  • 如果 a 要排在 b 前面, 則傳回 負數
  • 如果 a 跟 b 一樣或誰在前都無所謂, 則傳回 0
  • 如果 a 要排在 b 後面, 則傳回 正數
例如: 將數字由小排到大,
var points = [37, 100, 1, 5, 3 ,10];
points.sort(function(a, b){ return a-b; });
//[ 1,
//  3,
//  5,
//  10,
//  37,
//  100 ]
或將數字由大排到小,
var points = [37, 100, 1, 5, 3 ,10];
points.sort(function(a, b){ return b-a; });
//[ 100,
//  37,
//  10,
//  5,
//  3,
//  1 ]
sort 內定以文字排序的. 也就是先使用 toString 轉成字串, 然後再逐字比較其字碼 charCode, 程式碼大概是,
var defaultSort = function(a, b) {
    // 將 a, b 轉成字串
    var str_a = a.toString();
    var str_b = b.toString();
    // 取 a, b 字串長度較短, 為字串比較長度
    var len = str_a.length >= str_b.length? str_b.length: str_a.length;
    for (var i=0; i
於是, 我又轉念, 日光之下, 快跑的未必能贏; 力戰的未必得勝; 智慧的未必得糧食; 明哲的未必得資財; 靈巧的未必得喜悅, 所臨到眾人的是在乎當時的 機率.
一想到機率, 不可或缺的就是亂數. 還好, JS 有一個亂數產生器, 就歸在 Math 這個 Class 下. 而 Math.random() 會 隨機的傳回 0 到 1 之間的一個數. 而當將這個數減掉 0.5 時, 也就有將近 50% 的機會是負數. 所以當以這個演算法替代比較函式的傳回值時, 也就表示誰在排前面的機率大概是一半一半.
所以得到一個用來洗牌的比較函式, 如下
var shuffle = function() {
    return Math.random() - 0.5
}
對, 沒錯, 如果你要寫一個撲克牌遊戲, 就能用他來洗牌. 例如:
var card = 'A234567890IJK';
card.split('').sort(function() { return Math.random() - 0.5; }).join('');
// 'AJ968K5240I37'
上場吧 :P

沒有留言:

張貼留言