JavaScript 随机抽取不重复的数组元素,你真的会吗?
2017-05-18 14:51
656 查看
码匠 2017-05-14 11:54
HTML5学堂-码匠:从JavaScript数组(Array)中随机抽取不重复的元素,构成新数组(Array),拥有多种方法,来看看你用的方法性能如何?
![](http://p1.pstatp.com/large/212c00009c1552e8e7bf)
谁说我写的方法性能不好了,给我出来,哼!!!
相关说明:在此处依照“构思难度”和“性能”两方面出发,提供了四种不同的实现方法。
从第二次随机抽取的元素开始,需要将抽取的元素与当前新数组的已抽取元素相比较,如果相同,则重新抽取,并再次执行比较的操作。
JavaScript 代码实现
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var arrNum=[];
var ranNum = 5;
for(var i = 0; i < ranNum; i++) {
arrNum[i] = Math.floor(Math.random() * 10);
if(i > 0) {
for(var j = 0; j < i; j++) {
if(arrNum[j] == arrNum[i]) {
i--;
break;
}
}
}
}
方法实现难度与执行效率分析
在代码编写方面,涉及循环语句和条件语句的多层嵌套,这种方法比较容易想到,但编写复杂度较高,执行效率上来说很低,随着元素的抽取,要比较的次数越来越多,“失败的抽取”概率越来越大,整体效率低下。
![](http://p3.pstatp.com/large/1f8e0004439f6a101347)
这个方法的性能也太糟糕了吧~真不如我写的!!!
当获取新元素时,为该元素添加一个属性标记,再抽取一个元素之后,先判断是否有属性标记,如果已被标记,则说明该元素已被抽取,此时重新抽取。
JavaScript 代码实现
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var ranNum = 5;
var hash = {};
var result = [];
while(ranNum > 0) {
var ran = Math.floor(Math.random() * arr.length);
if (!hash[ran]) {
hash[ran] = 1;
result.push(ran);
ranNum--;
};
}
方法实现难度与执行效率分析
和第一种方法相比,编写复杂度较低,只需要使用循环语句和条件语句配合即可实现,节省了第一种方法中依次比较的步骤,但依旧存在“失败抽取”的现象,而且失败抽取的概率没有发生任何变化。
![](http://p3.pstatp.com/large/2131000086df2340ee60)
文章干货太多,先看看妹子,养养眼~~~不错,继续往下看文章
基本实现思路
该方法的基本原理是,在抽取一个元素之后,将该元素与数组末端的最后一个元素交换,然后将数组最后一个元素扔掉。
随着比较的进行,每次被抽取的元素都被交换到了数组末端,再被扔掉,数组长度也越来越短。
方法实现难度与执行效率分析
这种方法不太容易想到,但它的编写复杂度是三者中最低的,而性能也是最好的,由于每次比较之后,都将已抽取的元素删除了,因此并不会出现失败的抽取,更不需要做什么比较了。
实现思路演示
![](http://p3.pstatp.com/large/2130000098e4efa50c51)
JavaScript 随机抽取不重复的数组元素 - 交换法
JavaScript 代码实现 - 第一步
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [ ];
var ranNum = 5;
for (var i = 0; i < ranNum; i++) {
var ran = Math.floor(Math.random() * arr.length);
result.push(arr[ran]);
var center = arr[ran];
arr[ran] = arr[arr.length - 1];
arr[arr.length - 1] = center;
arr = arr.slice(0, arr.length - 1);
};
JavaScript 代码实现 - 优化
仔细观察第一步的代码中,有哪些步骤是不必须的?
交换法中,最重要的是两个点,第一,每次当前元素会被数组末尾元素所替代。第二,每次随机数的范围越来越小,数组长度越来越短。
也就是说,我们只要保证当前元素被末尾元素替代,并不断减小随机数范围,“数组长度”和“数组末尾的元素值”是可以忽略的。
去掉“数组长度”的控制,并且稍加修改代码,就变成了这样:
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [ ];
var ranNum = 5;
for (var i = 0; i < ranNum; i++) {
var ran = Math.floor(Math.random() * (arr.length - i));
result.push(arr[ran]);
var center = arr[ran];
arr[ran] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = center;
};
之后,我们取消“处理数组末尾的元素”,代码会得到进一步优化(优化后的代码如下)。
![](http://p3.pstatp.com/large/213000009dc325168d16)
这个方法真牛逼呀~~~吓死宝宝了
优化后的JavaScript成品代码
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [ ];
var ranNum = 5;
for (var i = 0; i < ranNum; i++) {
var ran = Math.floor(Math.random() * (arr.length - i));
result.push(arr[ran]);
arr[ran] = arr[arr.length - i - 1];
};
优化后的实现逻辑
![](http://p1.pstatp.com/large/2130000099f536c3094a)
JavaScript 随机抽取不重复的数组元素 - 交换法
利用splice方法,将抽取到的元素从数组当中删除掉,并利用splice方法返回值,将抽取到的元素存储(push)到结果数组当中。
JavaScript 代码实现
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [];
var ranNum = 5;
for (var i = 0; i < ranNum; i++) {
var ran = Math.floor(Math.random() * arr.length);
result.push(arr.splice(ran, 1)[0]);
};
方法实现难度与执行效率分析
该方法和第三种方法类似,但在实现方式上有所不同,也很快捷方便,每次抽取只需要进行截取和“抽取元素”的存取即可。并不会有重复的“失败抽取”和比较。
![](http://p9.pstatp.com/large/1f8e00044536ce017924)
我看上你这个方法了~~
![](http://p1.pstatp.com/large/21300000a0daaa3e8a04)
一般人我不告诉他~~~~
![](http://p9.pstatp.com/large/18ab0001e7e73f48fd71)
HTML5学堂(码匠) - https://weixin.mj216.com/
HTML5学堂-码匠:从JavaScript数组(Array)中随机抽取不重复的元素,构成新数组(Array),拥有多种方法,来看看你用的方法性能如何?
谁说我写的方法性能不好了,给我出来,哼!!!
JavaScript 效果的功能需求
从一个JavaScript数组当中,随机抽取数个元素,构成新数组,要求这些元素不能重复。(即随机获取不重复的数组元素)相关说明:在此处依照“构思难度”和“性能”两方面出发,提供了四种不同的实现方法。
方法1:较为“传统”的实现方法
基本实现思路从第二次随机抽取的元素开始,需要将抽取的元素与当前新数组的已抽取元素相比较,如果相同,则重新抽取,并再次执行比较的操作。
JavaScript 代码实现
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var arrNum=[];
var ranNum = 5;
for(var i = 0; i < ranNum; i++) {
arrNum[i] = Math.floor(Math.random() * 10);
if(i > 0) {
for(var j = 0; j < i; j++) {
if(arrNum[j] == arrNum[i]) {
i--;
break;
}
}
}
}
方法实现难度与执行效率分析
在代码编写方面,涉及循环语句和条件语句的多层嵌套,这种方法比较容易想到,但编写复杂度较高,执行效率上来说很低,随着元素的抽取,要比较的次数越来越多,“失败的抽取”概率越来越大,整体效率低下。
这个方法的性能也太糟糕了吧~真不如我写的!!!
方法2:标记法 / 自定义属性法
基本实现思路当获取新元素时,为该元素添加一个属性标记,再抽取一个元素之后,先判断是否有属性标记,如果已被标记,则说明该元素已被抽取,此时重新抽取。
JavaScript 代码实现
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var ranNum = 5;
var hash = {};
var result = [];
while(ranNum > 0) {
var ran = Math.floor(Math.random() * arr.length);
if (!hash[ran]) {
hash[ran] = 1;
result.push(ran);
ranNum--;
};
}
方法实现难度与执行效率分析
和第一种方法相比,编写复杂度较低,只需要使用循环语句和条件语句配合即可实现,节省了第一种方法中依次比较的步骤,但依旧存在“失败抽取”的现象,而且失败抽取的概率没有发生任何变化。
文章干货太多,先看看妹子,养养眼~~~不错,继续往下看文章
方法3:交换法
第三种方法是自己最喜欢的(“交换法”的名字是自己起的),也是自己在使用的。基本实现思路
该方法的基本原理是,在抽取一个元素之后,将该元素与数组末端的最后一个元素交换,然后将数组最后一个元素扔掉。
随着比较的进行,每次被抽取的元素都被交换到了数组末端,再被扔掉,数组长度也越来越短。
方法实现难度与执行效率分析
这种方法不太容易想到,但它的编写复杂度是三者中最低的,而性能也是最好的,由于每次比较之后,都将已抽取的元素删除了,因此并不会出现失败的抽取,更不需要做什么比较了。
实现思路演示
JavaScript 随机抽取不重复的数组元素 - 交换法
JavaScript 代码实现 - 第一步
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [ ];
var ranNum = 5;
for (var i = 0; i < ranNum; i++) {
var ran = Math.floor(Math.random() * arr.length);
result.push(arr[ran]);
var center = arr[ran];
arr[ran] = arr[arr.length - 1];
arr[arr.length - 1] = center;
arr = arr.slice(0, arr.length - 1);
};
JavaScript 代码实现 - 优化
仔细观察第一步的代码中,有哪些步骤是不必须的?
交换法中,最重要的是两个点,第一,每次当前元素会被数组末尾元素所替代。第二,每次随机数的范围越来越小,数组长度越来越短。
也就是说,我们只要保证当前元素被末尾元素替代,并不断减小随机数范围,“数组长度”和“数组末尾的元素值”是可以忽略的。
去掉“数组长度”的控制,并且稍加修改代码,就变成了这样:
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [ ];
var ranNum = 5;
for (var i = 0; i < ranNum; i++) {
var ran = Math.floor(Math.random() * (arr.length - i));
result.push(arr[ran]);
var center = arr[ran];
arr[ran] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = center;
};
之后,我们取消“处理数组末尾的元素”,代码会得到进一步优化(优化后的代码如下)。
这个方法真牛逼呀~~~吓死宝宝了
优化后的JavaScript成品代码
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [ ];
var ranNum = 5;
for (var i = 0; i < ranNum; i++) {
var ran = Math.floor(Math.random() * (arr.length - i));
result.push(arr[ran]);
arr[ran] = arr[arr.length - i - 1];
};
优化后的实现逻辑
JavaScript 随机抽取不重复的数组元素 - 交换法
方法4:随用随删
基本实现思路利用splice方法,将抽取到的元素从数组当中删除掉,并利用splice方法返回值,将抽取到的元素存储(push)到结果数组当中。
JavaScript 代码实现
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [];
var ranNum = 5;
for (var i = 0; i < ranNum; i++) {
var ran = Math.floor(Math.random() * arr.length);
result.push(arr.splice(ran, 1)[0]);
};
方法实现难度与执行效率分析
该方法和第三种方法类似,但在实现方式上有所不同,也很快捷方便,每次抽取只需要进行截取和“抽取元素”的存取即可。并不会有重复的“失败抽取”和比较。
我看上你这个方法了~~
额外要说的
为何要那么重点讲解第三种方法呢?一般人我不告诉他~~~~
HTML5学堂(码匠) - https://weixin.mj216.com/
相关文章推荐
- 关于从list或者数组中随机抽取部分不重复元素的问题探究
- 从数组和List中随机抽取若干不重复的元素.
- 【实践】js实现随机不重复抽取数组中元素
- javascript如何判断数组内元素是否重复的方法集锦
- javascript 过滤数组重复元素
- javascript 在数组中移除重复元素
- javascript 返回数组中不重复的元素
- 从数组中随机抽取几个元素形成新的数组
- 写一个函数,参数为$n,生成一个数组,其元素为1~$n,各元素位置随机排列,不得重复
- php从数组中随机抽取一些元素
- C++[算法]给定一个具有100个元素的数组,请对该数组随机赋值1-100,不能出现重复的值
- js获取数组任意个不重复的随机数组元素 原创
- Javascript 去除数组的重复元素
- javascript剔除数组重复元素的简单方法
- JavaScript去掉数组中的重复元素
- Javascript实践-去除数组的重复元素
- 双色球实例,用boolean数组做标记,随机抽取不重复的球
- javascript过滤数组中重复的元素
- 随机从长度未知的数组中抽取数字,且保证每个元素被抽到的概率相同