精品欧美一区二区三区在线观看 _久久久久国色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ù)棧公眾號

www.神马久久| 搞黄网站在线观看| 国产精品一二| 正在播放亚洲1区| 亚洲欧美偷拍另类| 国产激情小视频在线| 成人h版在线观看| 久久男人av| 国产**成人网毛片九色| 欧美诱惑福利视频| 99久久久免费精品| 国产成人福利av| 日本精品视频一区二区三区| av动漫免费观看| 日本激情一区二区三区| 日韩国产精品久久久久久亚洲| 久久精品国产亚洲精品2020| 国产精品揄拍100视频| 日韩三级一区| 欧美日韩另类字幕中文| 黄色网zhan| 国产在线日本| 波波电影院一区二区三区| 国产精品自产拍在线观看中文| 国产一级片免费观看| 日韩成人高清| 岛国视频午夜一区免费在线观看| 在线综合视频网站| 男男激情在线| 99精品国产热久久91蜜凸| 亚洲va久久久噜噜噜| 精品无码一区二区三区的天堂| 精品91视频| 伦伦影院午夜日韩欧美限制| 久久久久久国产免费a片| 另类尿喷潮videofree| 日韩欧美国产三级| 99国产精品久久久久久| 在线成人视屏| 欧美日韩在线视频一区二区| 人人妻人人做人人爽| 国产在线观看a| 国产精品夫妻自拍| 日本午夜一区二区三区| 久久这里精品| 久久综合色综合88| 精选一区二区三区四区五区| 亚洲国产精品久久人人爱潘金莲 | 亚洲视频在线a| 高清在线视频不卡| 亚洲综合清纯丝袜自拍| 色哺乳xxxxhd奶水米仓惠香| 9191在线播放| 亚洲激情图片一区| 视频一区二区视频| 黄色av网站在线播放| 中文字幕综合网| 先锋影音男人资源| 成人免费看片| 亚洲精品v日韩精品| 好色先生视频污| 污污视频在线| 亚洲成在人线在线播放| 国产中文字幕二区| 密臀av在线播放| 91国产视频在线观看| 波多野结衣天堂| 开心久久婷婷综合中文字幕| 欧美精品久久99久久在免费线| 女人高潮一级片| 日韩免费精品| 亚洲精品美女网站| 亚洲国产天堂av| 99精品在线| 色综合视频网站| 欧美一级特黄视频| 日韩精品成人一区二区三区| 国产精品一区二区三| 亚洲欧美日韩一区二区三区四区| 美女网站一区二区| 亚洲伊人一本大道中文字幕| 亚洲精品综合网| 久久欧美一区二区| 亚洲欧洲日夜超级视频| 性欧美ⅴideo另类hd| 黄网站色欧美视频| 天天干天天综合| 91久久偷偷做嫩草影院电| 日韩国产一区三区| 后入内射无码人妻一区| 欧美日本中文| 国产极品精品在线观看| 国产视频在线观看免费| 91色porny| 伊人av成人| av手机在线观看| 欧美性淫爽ww久久久久无| 手机看片国产精品| 中文字幕中文字幕精品| y97精品国产97久久久久久| 国产无码精品一区二区| 美女国产一区二区| 国产欧美日韩一区二区三区| av电影在线网| 亚洲国产成人tv| 国产成人黄色网址| 老牛影视av一区二区在线观看| 日韩专区在线观看| 西西44rtwww国产精品| 久久爱www久久做| 美女黄毛**国产精品啪啪| 成人午夜在线影视| 欧美丝袜丝交足nylons| 精品国产av色一区二区深夜久久| 999成人网| 国产成人精品最新| 农村少妇久久久久久久| 日韩一区日韩二区| 日本xxxxxxx免费视频| 91在线一区| 不卡av电影在线观看| 国内av在线播放| 久久免费视频色| 青青在线免费观看| 精品国产乱码久久久久久樱花| 国产亚洲xxx| 免费在线不卡视频| 丁香啪啪综合成人亚洲小说 | 中文字幕一二三四区| 欧美日本三区| 亚洲一区二区久久久久久久 | 久久久久久亚洲精品不卡| 国产精品嫩草影院精东| 欧美国产精品一区二区三区| 看av免费毛片手机播放| 国产精品超碰| 国内精品一区二区三区| 国产极品999| 亚洲色大成网站www久久九九| 日韩爱爱小视频| 国产免费播放一区二区| 青草青草久热精品视频在线网站| 少妇无码一区二区三区| 亚洲国产日韩a在线播放| 久久久久久无码精品人妻一区二区| 婷婷综合社区| 亚洲一区二区免费在线| 亚洲夜夜综合| 欧美videossexotv100| 青娱乐国产在线视频| 国产精品911| 久青草视频在线播放| 日韩欧美一级| 久久久久久久国产精品视频| 欧美 中文字幕| 性欧美疯狂xxxxbbbb| 国产成人av无码精品| 中文一区二区| 明星裸体视频一区二区| av在线日韩| 色妞色视频一区二区三区四区| 中文字幕一二区| 国产精品不卡在线| 久久久国产精品久久久| 伊人精品视频| 欧洲精品久久| 国产精品久久久久久av公交车| 色综合久久88色综合天天看泰| 高潮一区二区三区乱码| 黄色成人av在线| 一级片久久久久| 激情综合色播激情啊| 大陆极品少妇内射aaaaaa| 国产 日韩 欧美 综合 一区| 欧美与黑人午夜性猛交久久久| 国产小视频在线| 欧美精品高清视频| 国产午夜福利精品| 国产女人18毛片水真多成人如厕| mm131国产精品| 国产精品s色| 免费av在线一区二区| 日韩成人免费av| 欧美精品videosex性欧美| 毛片网站在线| 欧美丰满一区二区免费视频| 国产第一页在线播放| 国产亚洲综合在线| 巨乳女教师的诱惑| 老司机一区二区三区| 少妇熟女一区二区| 精品午夜电影| 成人免费视频网址| 阿v视频在线| 日韩亚洲一区二区| 秋霞欧美在线观看| 欧美色涩在线第一页| 久久成人在线观看| 久久久欧美精品sm网站| 无套内谢丰满少妇中文字幕| 久久精品毛片| 又大又硬又爽免费视频| 日韩欧美午夜| 久久99精品久久久久久秒播放器| 亚洲网站免费| 国产成人av在线播放| 影音先锋男人资源在线| 中文字幕精品久久| 午夜视频免费看| 日韩欧美国产综合在线一区二区三区| 免费黄色av片| 亚洲午夜久久久久久久久久久 | 亚洲成人精品影院| 精品国产视频在线观看| 国产欧美在线观看一区| 精品国产av色一区二区深夜久久 | 久久福利一区| 久久久久久久香蕉| 99久久激情| 日韩动漫在线观看| 久本草在线中文字幕亚洲| 国产日韩中文字幕在线| 欧美成a人片在线观看久| 欧美精品videossex性护士| 黄色网页在线观看| 中文字幕亚洲一区二区三区五十路| 亚洲色图 校园春色| 欧美tk丨vk视频| 99国产精品一区二区三区| 欧美揉bbbbb揉bbbbb| 精品国产一区二区三区四| 午夜影视日本亚洲欧洲精品| 久久免费视频精品| 亚洲免费伊人电影| 美女视频久久久| 中文字幕电影一区| 精品国产成人亚洲午夜福利| 久久久综合网站| 中日韩精品一区二区三区 | 国产一区二区三区高清| 日本高清精品| 97人人澡人人爽| 一区二区网站| 成人在线看片| 136国产福利精品导航网址应用| 亚洲在线观看视频网站| 成人51免费| 亚洲综合日韩中文字幕v在线| 91麻豆精品| 亚洲va久久久噜噜噜| 亚洲精品在线a| 国产高清精品一区二区| 福利在线一区| 久久伊人一区| 国内精品视频在线观看| 日韩一区二区三区资源| 成人网18免费网站| 麻豆中文字幕在线观看| 在线免费观看日本欧美爱情大片| 欧美三级午夜理伦三级老人| 亚洲欧美在线专区| 久久精品在线免费视频| 欧美另类视频| 国产白丝袜美女久久久久| 欧美专区18| 小明看看成人免费视频| 国产一区二区三区免费观看| 国产精久久久久| 93久久精品日日躁夜夜躁欧美| 中文字幕一区二区人妻在线不卡| 久久九九久久九九| 国产喷水在线观看| 一区二区视频在线| 欧美激情亚洲综合| 欧美自拍丝袜亚洲| 国产免费av电影| 亚洲国产精品热久久| 精品欧美不卡一区二区在线观看 | 国产精品一区二区免费不卡| av免费观看不卡| 国产三级精品在线| 日本黄色小说视频| 日韩欧美视频一区二区三区| 亚洲中文字幕在线一区| 精品国产一区二区亚洲人成毛片 | 久久高清视频免费| freexxx性亚洲精品| 国产精品视频自在线| 99久久免费精品国产72精品九九| 欧美日韩一区二区三| 中国精品18videos性欧美| 欧美黑人经典片免费观看| 麻豆视频一区二区| 中文字幕天堂av| 国产精品久久看| 激情五月色婷婷| 欧美二区乱c少妇| 欧美一区二区少妇| 美日韩精品免费观看视频| sis001欧美| 99re国产| 91亚洲一区| 一本大道熟女人妻中文字幕在线| 国产一区亚洲一区| 亚洲一级中文字幕| 一区二区三区加勒比av| 成人免费一区二区三区| 亚洲白拍色综合图区| 嫩草在线视频| 国产成人精品在线视频| 老牛国内精品亚洲成av人片| 在线观看17c| 麻豆精品国产91久久久久久| 亚洲精品乱码久久久久久不卡| 亚洲欧美偷拍卡通变态| 国产偷人爽久久久久久老妇app| 亚洲国产精品字幕| 欧美人与性动交α欧美精品济南到| 国产精品视频导航| 婷婷亚洲成人| 日韩a级在线观看| 国产高清视频一区| 制服丨自拍丨欧美丨动漫丨| 色噜噜狠狠成人中文综合| 粉嫩av一区二区夜夜嗨| 欧美猛少妇色xxxxx| 小说区图片区亚洲| 色姑娘综合网| 日韩国产精品久久| 丰满少妇高潮一区二区| 欧美日韩精品在线观看| 婷婷丁香花五月天| 久久久亚洲国产天美传媒修理工| 2020国产精品小视频| 亚洲毛片aa| 久久精品99久久久| 亚洲天堂av中文字幕| 欧美专区日韩专区| 加勒比一区二区三区在线| 欧美在线视频导航| 亚洲区小说区| 成人观看免费完整观看| 91亚洲午夜精品久久久久久| 天天爽夜夜爽夜夜爽精品| 亚洲精品理论电影| 在线天堂资源www在线污| 久久精品99久久| 媚黑女一区二区| 亚洲天堂岛国片| 欧美人与性动xxxx| 国产二区三区在线| 99re视频| 亚洲精品社区| 成都免费高清电影| 欧美亚洲愉拍一区二区| 99中文字幕一区| 91在线中文字幕| 国产综合色产| 精品人妻一区二区三区香蕉| 欧美性感美女h网站在线观看免费| 亚洲三级中文字幕| 国产成人精品午夜| 欧美激情理论| 不卡的一区二区| 亚洲成人手机在线| 每日更新av在线播放| 国产综合香蕉五月婷在线| 影音先锋日韩在线| 日批在线观看视频| 91官网在线免费观看| 色视频在线免费观看| 亚洲一区二区三区在线免费观看| 亚洲视频中文| 国产美女免费无遮挡| 欧美剧在线免费观看网站 | 一本一本久久a久久综合精品| 亚洲少妇一区二区| 欧美性69xxxx肥| 日本在线观看视频| 成人资源视频网站免费| 久久精品网址| 国产黄色片在线免费观看| 亚洲国产欧美一区| jizz亚洲女人高潮大叫| 中文字幕の友人北条麻妃| 99热精品国产| 96亚洲精品久久久蜜桃| 久久久亚洲网站| 欧美限制电影| 一二三区视频在线观看| 91精品91久久久中77777| 色呦呦呦在线观看| 欧美一区2区三区4区公司二百 | 91青青草免费观看| 亚洲一卡久久| 国产人妻精品一区二区三区不卡| 日韩成人在线视频网站| 99精品女人在线观看免费视频| 欧美 日韩 国产在线观看| 亚洲欧洲精品一区二区三区|