精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

關(guān)于JavaScript的數(shù)組隨機排序

開發(fā) 前端
如果要將數(shù)組隨機排序,千萬不要再用(a, b) => Math.random() - 0.5這樣的方法。目前而言,F(xiàn)isher–Yates shuffle 算法應(yīng)該是最好的選擇。

JavaScript 開發(fā)中有時會遇到要將一個數(shù)組隨機排序(shuffle)的需求,一個常見的寫法是這樣:

  1. function shuffle(arr) { 
  2.  
  3.    arr.sort(function () { 
  4.  
  5.       return Math.random() - 0.5; 
  6.  
  7.    }); 
  8.  

 

或者使用更簡潔的 ES6 的寫法:

  1. function shuffle(arr) { 
  2.  
  3.     arr.sort(() => Math.random() - 0.5); 
  4.  

 

我也曾經(jīng)經(jīng)常使用這種寫法,不久前才意識到,這種寫法是有問題的,它并不能真正地隨機打亂數(shù)組。

問題

看下面的代碼,我們生成一個長度為 10 的數(shù)組['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],使用上面的方法將數(shù)組亂序,執(zhí)行多次后,會發(fā)現(xiàn)每個元素仍然有很大機率在它原來的位置附近出現(xiàn)。

  1. let n = 10000; 
  2.  
  3. let count = (new Array(10)).fill(0); 
  4.  
  5.   
  6.  
  7. for (let i = 0; i < n; i ++) { 
  8.  
  9.     let arr = ['a''b''c''d''e''f''g''h''i''j']; 
  10.  
  11.     arr.sort(() => Math.random() - 0.5); 
  12.  
  13.     count[arr.indexOf('a')]++; 
  14.  
  15.  
  16.   
  17.  
  18. console.log(count); 

 

在 Node.JS 6 中執(zhí)行,輸出[ 2891, 2928, 1927, 1125, 579, 270, 151, 76, 34, 19 ](帶有一定隨機性,每次結(jié)果都不同,但大致分布應(yīng)該一致),即進行 10000 次排序后,字母'a'(數(shù)組中的***個元素)有約 2891 次出現(xiàn)在***個位置、2928 次出現(xiàn)在第二個位置,與之對應(yīng)的只有 19 次出現(xiàn)在***一個位置。如果把這個分布繪制成圖像,會是下面這樣:

 

 

類似地,我們可以算出字母'f'(數(shù)組中的第六個元素)在各個位置出現(xiàn)的分布為[ 312, 294, 579, 1012, 1781, 2232, 1758, 1129, 586, 317 ],圖像如下:

 

 

如果排序真的是隨機的,那么每個元素在每個位置出現(xiàn)的概率都應(yīng)該一樣,實驗結(jié)果各個位置的數(shù)字應(yīng)該很接近,而不應(yīng)像現(xiàn)在這樣明顯地集中在原來位置附近。因此,我們可以認(rèn)為,使用形如arr.sort(() => Math.random() - 0.5)這樣的方法得到的并不是真正的隨機排序。

另外,需要注意的是上面的分布僅適用于數(shù)組長度不超過 10 的情況,如果數(shù)組更長,比如長度為 11,則會是另一種分布。比如:

  1. let a = ['a''b''c''d''e''f''g''h''i''j''k']; // 長度為11 
  2.  
  3. let n = 10000; 
  4.  
  5. let count = (new Array(a.length)).fill(0); 
  6.  
  7.   
  8.  
  9. for (let i = 0; i < n; i ++) { 
  10.  
  11.     let arr = [].concat(a); 
  12.  
  13.     arr.sort(() => Math.random() - 0.5); 
  14.  
  15.     count[arr.indexOf('a')]++; 
  16.  
  17.  
  18.   
  19.  
  20. console.log(count); 

 

在 Node.JS 6 中執(zhí)行,結(jié)果為[ 785, 819, 594, 679, 941, 1067, 932, 697, 624, 986, 1876 ],其中***個元素'a'的分布圖如下:

sort_03

分布不同的原因是 v8 引擎中針對短數(shù)組和長數(shù)組使用了不同的排序方法(下面會講)。可以看到,兩種算法的結(jié)果雖然不同,但都明顯不夠均勻。

國外有人寫了一個Shuffle算法可視化的頁面,在上面可以更直觀地看到使用arr.sort(() => Math.random() - 0.5)的確是很不隨機的。

探索

看了一下ECMAScript中關(guān)于Array.prototype.sort(comparefn)的標(biāo)準(zhǔn),其中并沒有規(guī)定具體的實現(xiàn)算法,但是提到一點:

Calling comparefn(a,b) always returns the same value v when given a specific pair of values a and b as its two arguments.

也就是說,對同一組a、b的值,comparefn(a, b)需要總是返回相同的值。而上面的() => Math.random() - 0.5(即(a, b) => Math.random() - 0.5)顯然不滿足這個條件。

翻看v8引擎數(shù)組部分的源碼,注意到它出于對性能的考慮,對短數(shù)組使用的是插入排序,對長數(shù)組則使用了快速排序,至此,也就能理解為什么() => Math.random() - 0.5并不能真正隨機打亂數(shù)組排序了。(有一個沒明白的地方:源碼中說的是對長度小于等于 22 的使用插入排序,大于 22 的使用快排,但實際測試結(jié)果顯示分界長度是 10。)

解決方案

知道問題所在,解決方案也就比較簡單了。

方案一

既然(a, b) => Math.random() - 0.5的問題是不能保證針對同一組a、b每次返回的值相同,那么我們不妨將數(shù)組元素改造一下,比如將每個元素i改造為:

  1. let new_i = { 
  2.  
  3.     v: i, 
  4.  
  5.     r: Math.random() 
  6.  
  7. }; 

 

即將它改造為一個對象,原來的值存儲在鍵v中,同時給它增加一個鍵r,值為一個隨機數(shù),然后排序時比較這個隨機數(shù):

  1. arr.sort((a, b) => a.r - b.r); 

完整代碼如下:

  1. function shuffle(arr) { 
  2.  
  3.     let new_arr = arr.map(i => ({v: i, r: Math.random()})); 
  4.  
  5.     new_arr.sort((a, b) => a.r - b.r); 
  6.  
  7.     arr.splice(0, arr.length, ...new_arr.map(i => i.v)); 
  8.  
  9.  
  10.   
  11.  
  12. let a = ['a''b''c''d''e''f''g''h''i''j']; 
  13.  
  14. let n = 10000; 
  15.  
  16. let count = (new Array(a.length)).fill(0); 
  17.  
  18.   
  19.  
  20. for (let i = 0; i < n; i ++) { 
  21.  
  22.     shuffle(a); 
  23.  
  24.     count[a.indexOf('a')]++; 
  25.  
  26.  
  27.   
  28.  
  29. console.log(count); 

 

一次執(zhí)行結(jié)果為:[ 1023, 991, 1007, 967, 990, 1032, 968, 1061, 990, 971 ]。多次驗證,同時在這兒查看shuffle(arr)函數(shù)結(jié)果的可視化分布,可以看到,這個方法可以認(rèn)為足夠隨機了。

方案二(Fisher–Yates shuffle)

需要注意的是,上面的方法雖然滿足隨機性要求了,但在性能上并不是很好,需要遍歷幾次數(shù)組,還要對數(shù)組進行splice等操作。

考察Lodash 庫中的 shuffle 算法,注意到它使用的實際上是Fisher–Yates 洗牌算法,這個算法由 Ronald Fisher 和 Frank Yates 于 1938 年提出,然后在 1964 年由 Richard Durstenfeld 改編為適用于電腦編程的版本。用偽代碼描述如下:

  1. -- To shuffle an array a of n elements (indices 0..n-1): 
  2.  
  3. for i from n−1 downto 1 do 
  4.  
  5.      j ← random integer such that 0 ≤ j ≤ i 
  6.  
  7.      exchange a[j] and a[i] 

 

一個實現(xiàn)如下(ES6):

  1. function shuffle(arr) { 
  2.  
  3.     let i = arr.length; 
  4.  
  5.     while (i) { 
  6.  
  7.         let j = Math.floor(Math.random() * i--); 
  8.  
  9.         [arr[j], arr[i]] = [arr[i], arr[j]]; 
  10.  
  11.     } 
  12.  

 

或者對應(yīng)的 ES5 版本:

  1. function shuffle(arr) { 
  2.  
  3.   var i = arr.length, t, j; 
  4.  
  5.   while (i) { 
  6.  
  7.     j = Math.floor(Math.random() * i--); 
  8.  
  9.     t = arr[i]; 
  10.  
  11.     arr[i] = arr[j]; 
  12.  
  13.     arr[j] = t; 
  14.  
  15.   } 
  16.  

 

小結(jié)

如果要將數(shù)組隨機排序,千萬不要再用(a, b) => Math.random() - 0.5這樣的方法。目前而言,F(xiàn)isher–Yates shuffle 算法應(yīng)該是***的選擇。 

責(zé)任編輯:龐桂玉 來源: 前端大全
相關(guān)推薦

2009-11-18 11:30:26

PHP數(shù)組排序

2010-10-08 13:21:03

JavaScript多維數(shù)組

2022-02-15 10:30:58

UUID

2011-05-25 10:03:00

JavaScriptwith

2020-11-26 08:12:24

JavaScript對象數(shù)組

2009-11-17 16:09:04

PHP二維數(shù)組排序

2019-10-30 08:53:46

JavaScript冒泡排序選擇排序

2011-05-25 11:25:23

快速排序Javascript

2009-08-13 10:35:05

Scala數(shù)組排序

2016-09-14 09:20:05

JavaScript閉包Web

2010-05-26 14:41:38

JavaScript

2011-04-13 14:04:14

Java數(shù)組

2021-02-05 05:28:31

恢復(fù)性能優(yōu)化

2025-08-12 09:11:25

2012-04-26 10:52:52

Java數(shù)組集合

2009-06-17 16:01:28

2016-12-21 09:35:55

JavaScript原生數(shù)組函數(shù)

2016-10-13 19:33:10

javascript數(shù)組indexOf

2019-07-17 14:06:45

JavaScript數(shù)組轉(zhuǎn)換

2014-01-22 09:46:42

JavaScript數(shù)組
點贊
收藏

51CTO技術(shù)棧公眾號

久久国产精品高清一区二区三区| 尤物视频最新网址| av理论在线观看| 国产精品一区二区在线播放| 欧美大成色www永久网站婷| 动漫av在线免费观看| xx欧美视频| 亚洲色图20p| 精品视频免费观看| 91国内精品久久久| 国产日韩免费| 麻豆一区二区在线观看| 波多野结衣先锋影音| 久久av日韩| 欧美性xxxxx| 亚洲国产一二三精品无码| 欧美日韩在线中文字幕| 国产乱码精品1区2区3区| 欧美亚州一区二区三区| 亚洲精品一区二三区不卡| 国产福利一区二区三区在线观看| 无码人妻丰满熟妇奶水区码| 欧美fxxxxxx另类| 亚洲香蕉av在线一区二区三区| 日本r级电影在线观看| 另类专区亚洲| 亚洲国产综合色| 熟妇熟女乱妇乱女网站| gogogo高清在线观看免费完整版| 成人性生交大片| 成人免费黄色网| 无码人妻精品一区二区三区不卡| 国产主播一区| 久久中文字幕在线| 免费看的黄色网| 亚洲宅男一区| 日韩精品亚洲视频| 麻豆精品国产传媒av| 日韩精品三级| 3751色影院一区二区三区| 99精品视频在线看| av影院在线| 亚洲一区二区三区四区中文字幕| 正在播放一区二区三区| 福利视频在线看| 久久综合一区二区| 久久亚洲免费| 色哟哟在线观看| 国产自产v一区二区三区c| 国产精品久久久久久久久久久久久 | 亚洲一卡二卡在线| 天堂一区二区在线| 国产成人精品网站| 懂色av蜜臀av粉嫩av分享吧最新章节| 国产精品五区| 午夜免费日韩视频| 日韩三级一区二区三区| 在线欧美亚洲| 97久久精品人搡人人玩| 精品午夜福利在线观看| 欧美日韩精品一本二本三本| 欧美日本啪啪无遮挡网站| 亚洲xxxx3d动漫| 2023国产精品久久久精品双| 久久精品精品电影网| 538精品在线视频| 国产精品vip| 91精品国产乱码久久久久久蜜臀| 久久青青草视频| 欧美一级播放| 国产欧美久久久久久| 国产原创中文av| 国产激情偷乱视频一区二区三区| 国产精品久久久久久久久久久久冷| 精品久久久久成人码免费动漫| 国产高清视频一区| 精品国产一区二区三区四区vr| 日韩在线观看视频一区二区三区| 99久久精品国产毛片| 精品蜜桃一区二区三区| 国产日本在线视频| 日韩一区日韩二区| 日韩极品视频在线观看| 蜜臀国产一区| 欧美日韩国产不卡| 人妻体内射精一区二区三区| 日韩精品社区| 日韩最新在线视频| 久久网免费视频| 首页综合国产亚洲丝袜| 91精品久久久久久久久久另类| 99视频在线观看免费| 26uuu色噜噜精品一区二区| 亚洲欧美丝袜| 91av久久| 欧美男同性恋视频网站| 婷婷五月精品中文字幕| 国产亚洲精品美女久久久久久久久久| 精品久久久av| 日韩精品在线不卡| 久久激情综合网| 国产偷久久久精品专区| 色网站免费在线观看| 亚洲国产aⅴ成人精品无吗| 玩弄japan白嫩少妇hd| 欧美成人一级| 亚洲天堂免费视频| 久久久精品国产sm调教网站| 日本免费在线视频不卡一不卡二| 国产66精品久久久久999小说 | 超碰91人人草人人干| 欧美啪啪小视频| 国产激情一区二区三区桃花岛亚洲| 欧美日韩亚洲综合一区二区三区激情在线 | 日韩中文字幕第一页| 黄色激情视频在线观看| 老司机午夜精品99久久| 精品国产免费久久久久久尖叫| 福利视频在线| 欧美少妇性性性| 熟女人妻在线视频| 狠久久av成人天堂| 亚洲a级在线观看| 在线国产91| 91成人国产精品| 日本一区二区三区网站| 欧美日韩国产亚洲一区| 91久久久在线| 日本精品在线| 欧美日韩你懂得| 国产高清一区二区三区四区| 一本色道精品久久一区二区三区| 999国内精品视频在线| 生活片a∨在线观看| 欧洲国产伦久久久久久久| 黄瓜视频污在线观看| 99精品视频免费| 国产一区二区在线网站| 9999在线视频| 亚洲国产一区二区三区四区| 精品人妻在线播放| 高清久久久久久| 免费在线黄网站| 99香蕉久久| 欧美激情在线视频二区| 亚洲精选一区二区三区| 亚洲精品伦理在线| 乳色吐息在线观看| 欧美成人午夜| av在线不卡观看| 2021中文字幕在线| 亚洲国产精品视频在线观看| 久久精品这里有| 不卡欧美aaaaa| 波多野结衣家庭教师在线播放| 美女扒开腿让男人桶爽久久动漫| 久久久久久久色| 天天色棕合合合合合合合| 黄色精品在线看| av网在线播放| 久久99国内精品| 玖玖精品在线视频| 亚洲一区二区电影| 69视频在线免费观看| 人人妻人人澡人人爽久久av| 一区二区三区欧美日韩| 精品熟女一区二区三区| 先锋影音久久| 亚洲黄色一区二区三区| 国产精品亚洲欧美日韩一区在线| 久久夜精品香蕉| 人妻va精品va欧美va| 欧美性69xxxx肥| 1024在线看片| 国产麻豆成人精品| 奇米精品一区二区三区| 精品一区二区三| 亚洲一区中文字幕在线观看| 超碰在线中文字幕| 一个色综合导航| www.午夜激情| 日韩人体视频一二区| 性少妇xx生活| av网站一区二区三区| 欧美性猛交xxx乱久交| 久久久久电影| 精品一区在线播放| 中文字幕日本一区| 97精品一区二区视频在线观看| 国产区视频在线| 日韩欧美一级在线播放| 国产精品久久久久久人| 一区在线播放视频| 黄色工厂在线观看| 激情五月播播久久久精品| 免费一级特黄特色毛片久久看| 欧美日韩一二| 极品尤物一区二区三区| 精品福利在线| 5566成人精品视频免费| 国产在线高清视频| 亚洲美女www午夜| 国产高潮流白浆喷水视频| 色狠狠桃花综合| 久久久美女视频| 国产精品久久久久婷婷二区次| 国产艳妇疯狂做爰视频| 免费成人在线观看视频| 可以在线看的av网站| 亚洲国产不卡| 日韩美女一区| 琪琪久久久久日韩精品| 成人av资源在线播放| 欧美xx视频| 久久免费视频网| 蜜桃av在线免费观看| 亚洲日韩中文字幕| 色窝窝无码一区二区三区成人网站| 911国产精品| 中文字幕乱码视频| 精品久久久久久久久久国产| 少妇人妻丰满做爰xxx| 欧美国产一区在线| 国产精品jizz| 成人永久看片免费视频天堂| 99九九99九九九99九他书对| 石原莉奈一区二区三区在线观看 | 免费看特级毛片| 欧美韩国一区二区| 久久成人激情视频| 91免费国产在线| 亚洲天堂2024| 成人激情动漫在线观看| 国产精品日日摸夜夜爽| 国产成人精品亚洲午夜麻豆| 黄色aaaaaa| 国产一区二区伦理| 国产无遮挡猛进猛出免费软件| 日韩精品一级二级| 北条麻妃视频在线| 美女网站久久| mm1313亚洲国产精品无码试看| 久久国产成人| 动漫av免费观看| 日韩综合在线视频| 国产成人手机视频| 日本中文字幕一区| 中文字幕一区二区三区四区在线视频| 久久成人精品| 黄色aaa级片| 久久精品99国产国产精| 在线能看的av网站| 国产一区二区免费视频| 手机在线免费毛片| 国产成人免费视频网站高清观看视频 | 国产一区在线看| www.51色.com| 成人免费视频caoporn| 欧产日产国产精品98| 99麻豆久久久国产精品免费| 在线免费观看污视频| 91原创在线视频| 久久久久亚洲av成人无码电影| 国产日本欧洲亚洲| 欧美性生给视频| 一区二区三区四区亚洲| 日本三级视频在线| 色综合久久综合中文综合网| 中文字幕二区三区| 日韩一卡二卡三卡国产欧美| 成人午夜精品福利免费| 国产视频亚洲精品| 最新97超碰在线| 欧美第一黄色网| 亚洲v.com| 国产日本欧美一区二区三区在线| 高清一区二区三区av| 国产在线一区二区三区欧美| 国产99久久久国产精品成人免费 | 亚洲人成网站免费播放| 九色综合日本| 国产精品久久久久久久久毛片 | 欧美精品久久久久久久久| 激情影院在线| 欧美孕妇性xx| 亚洲色图综合| 久久99蜜桃综合影院免费观看| 精品av一区二区| 亚洲天堂第一区| 香蕉亚洲视频| 先锋资源在线视频| 91丨porny丨国产入口| ass极品国模人体欣赏| 亚洲综合免费观看高清完整版| 国产精品久久久久久久久久久久久久久久久 | 午夜不卡一区| 好吊色欧美一区二区三区| 日本久久黄色| 精品少妇在线视频| 久久99在线观看| 中文字幕 亚洲一区| 亚洲欧美二区三区| 亚洲黄网在线观看| 欧美不卡在线视频| 9色在线观看| 2019国产精品自在线拍国产不卡| 亚洲青青久久| 日韩在线电影一区| 激情久久久久久久| 国产无遮挡猛进猛出免费软件| 99久久综合精品| 亚洲国产美女视频| 欧美无乱码久久久免费午夜一区| 国精产品一品二品国精品69xx | 亚洲精品久久久久中文字幕二区| 秋霞影院午夜丰满少妇在线视频| 97国产在线视频| 日韩精品一区二区三区中文在线| 午夜一区二区三区| 国产视频一区免费看| aaaaa黄色片| 中文字幕日韩欧美一区二区三区| 无码人妻一区二区三区线| 精品免费视频.| a视频在线播放| 国产美女直播视频一区| 一区二区三区视频免费观看| 国产精品va在线观看无码| 国产乱码精品一区二区三区av| 2017亚洲天堂| 欧美性生活大片视频| 蝌蚪视频在线播放| 欧美亚洲在线观看| 久久影视三级福利片| 日韩精品在线视频免费观看| 精品一区二区影视| 在线免费看视频| 欧美日韩三级一区二区| 国产二区在线播放| 日韩美女免费观看| 一区二区美女| 日韩毛片在线免费看| 久久久精品蜜桃| 精品人妻一区二区三区免费看| 精品无人区乱码1区2区3区在线| h片在线观看| 精品不卡一区二区三区| 一本色道久久| 亚洲欧美色图视频| 欧美日韩亚洲精品一区二区三区| 蜜桃视频在线观看www| 韩国三级日本三级少妇99| 任你躁在线精品免费| 免费无遮挡无码永久视频| 91啪亚洲精品| 国产免费www| 久久人人爽人人爽人人片亚洲| 精品国产亚洲日本| 毛片在线视频观看| 国产成人av一区| 国产无码精品一区二区| 日韩av在线网| 伊人久久高清| 一区二区三区免费看| 国产精品一区二区三区网站| 国产精品第56页| 精品中文视频在线| 国产激情久久| 无码人妻精品一区二区蜜桃百度| 国产99精品国产| 日韩精品在线观看免费| 亚洲亚裔videos黑人hd| 国产第一亚洲| 亚洲色欲久久久综合网东京热| eeuss影院一区二区三区| 在线观看免费av片| 日韩一中文字幕| 99香蕉久久| 狠狠热免费视频| 亚洲精品v日韩精品| 无码国产精品一区二区色情男同 | 久久久久久久久久一级| 日韩在线观看免费高清完整版| 最新精品在线| 人人干人人视频| 亚洲一区二区视频在线观看| 免费国产在线观看| 亚洲一区二区三区久久| 国产日韩欧美三级| 中文字幕资源站| 亚洲精品午夜精品| 豆花视频一区| 黄色高清无遮挡| 伊人性伊人情综合网| 黄网站在线观看| 成人自拍爱视频| 日本强好片久久久久久aaa| 国产亚洲精品码| 在线播放日韩精品| 卡通动漫国产精品|