js将数组随机打乱

原理:主要是将数组里的索引值随机打乱,然后将当前的索引值与随机变化之后的索引值互换。

1.首先遍历的开始是从最大的索引开始,然后逐次递减;

2.然后选取一个随机值randomIndex,这个随机值的产生是在0-len(即数组的长度)之间产生,由于这个值不能为len(因为数组的索引是从0开始的),只能为len-1,故只能向下取整Math.floor;

3.取到随机值之后,将这个随机值对应的数组值即arr[randomIndex]赋值给当前遍历的i对应的数组值即arr[i];

提示:这里要注意第三步,有的同学看到第三步之后,会这样写:arr[i] = arr[randomIndex]。这样写会导致一个什么样的错误呢?这样写会导致输出的数组中部分元素的值相同,如下图所示:

这是因为每一次遍历的时候,randomIndex是随机产生的,但是并不妨碍它们在这几次之中有个别几次是取到相同的值的,就比如上图中,randomIndex取值为了1的时候出现了三次,因为原数组中arr[1]=1,变化之后的数组中有三个1,所以randomIndex是取了三次1并分别赋值给了arr[i],其中i=5,i=3,i=2。

因此,要先定义个变量itemAtIndex来先保存arr[randomIndex]的值,然后将当前遍历的i对应的值赋值给索引值randomIndex对应的数组值,即arr[randomIndex] = arr[i],最后将之前保存arr[randomIndex]的值的itemAtIndex赋值给arr[i]

最终代码如下:

  function getArrRandomly(arr) {

    var len = arr.length;

    //首先从最大的数开始遍历,之后递减

    for(var i=len-1;i>=0;i--){

      //随机索引值randomIndex是从0-arr.length中随机抽取的

      var randomIndex = Math.floor(Math.random() * (i+1));

      //下面三句相当于把从数组中随机抽取到的值与当前遍历的值互换位置

      var itemIndex = arr[randomIndex];

      arr[randomIndex] = arr[i];

      arr[i] = itemIndex;

    }

    //每一次的遍历都相当于把从数组中随机抽取(不重复)的一个元素放到数组的最后面(索引顺序为:len-1,len-2,len-3......0)

    return arr;

  },

最后,爱思考的同学可能就会问一个问题了。为什么遍历的时候要从i的取值最大时开始呢?可不可以就从i=0开始呢?

答案只能说勉强可以,但是不推荐。思路是差不多的,这里就不再赘述,实现如下代码:

function getArrRandomly(arr) {

var len = arr.length;

//首先从最小的数开始遍历,之后递增

for (var i = 0; i < len; i++) {

var randomIndex = Math.floor(Math.random()*(len-i));//这里一定要注意,后面不管是(i+1)还是(len-i),它们是时变的。

var itemAtIndex = arr[randomIndex];

arr[randomIndex] = arr[i];

arr[i] = itemAtIndex;

}

//每一次遍历,都相当于把从数组中随机抽取(不重复,因为)一个元素放到数组的最前面(索引顺序为0,1,2...len-1)

return arr;

}

//下面是调用这个函数

var arr = [0,1,2,3,4,5,6,7,8];

var newArray = getArrRandomly(arr);

console.log(newArray)

为什么不推荐用遍历递增的形式呢?

因为遍历递减的话,从最大的索引值开始,比如该问题中从i=8开始,不管随机值取什么(0-8之间),这个随机索引对应的数组值是被放入到arr[8]的位置上的;然后在第二次遍历的时候,i=7,这个时候,这个随机值只能取0-7之间的值,因为i是递减的,大家可以从var randomIndex = Math.floor(Math.random() * (i+1))可以看出,所以随机值是取不到8的,故arr[8]这个值就实锤了,也就是说了第二次遍历完后,arr[7]的位置也会被实锤,直到arr[0]实锤完毕。

而遍历递减就不同了,它无法实现arr[i]某个索引值实锤,就比如上面的代码,var randomIndex = Math.floor(Math.random() * (len-i)),这里randomIndex是连续九次都可以取到0这个值,无法一次性实锤。虽然这个方法最后也会把数组打乱,但是细心的同学会发现,不管运行几次程序,打乱后的数组的第一个元素,不是8就是0。所以这个方法并不推荐。

原文:https://blog.csdn.net/Charles_Tian/article/details/80342438

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容