如何高效的提取随机数据
来源:互联网 发布:java连接db2数据库 编辑:程序博客网 时间:2024/04/29 05:22
对于程序员来说,“随机”一词再熟悉不过了。一听到“随机”,我们脑海中便会出现一个单词“random”,和一系列的算法实现。而这,已经成为了程序员的条件反射!今天博主就跟大家聊一聊随机这件事。
想必很多朋友都考过驾照,在科目一中有一套交规题库,考试的时候系统会从这些题库中随机抽取100道题目作为考题(考过的人都知道这些题库又分成几大类,真正考试是从每一类中随机出N道题目,最后加在一起凑成100道,为了方便理解,我们姑且忽略这个分类),下面就来看看如何实现随机抽取考题这一算法。
二逼青年这样写:
function getRandomArray(list, total) { var startIndex = Math.floor(Math.random() * (list.length - total)); return list.slice(startIndex, total);}
直接从原数组中截取指定长度的数组,而截取的起始位置随机获得。代码只有2行,简洁明了,一气呵成。BUT,很明显这种写法有个致命缺陷——每次取出的数组都是固定顺序的,而不是完全自由组合的,所以这种写法是“伪随机”,不可取。
文艺青年这样写:
function getRandomArray(list, total) { if (!list || !list.slice) return []; if (list.length <= total) return list; var result = []; function rand() { var index = Math.floor(Math.random() * list.length); if (result.indexOf(list[index]) == -1) { result.push(list[index]); } if (result.length < total) { rand(); } } rand(); return result;}
首先做了容错处理,避免非法调用时抛出异常。然后写了递归函数,每次从原数组随机获取不重复的一项,直到满足结果集长度。看上去已经完美实现了随机的需求,但总感觉有点别扭——靠递归排除重复可能性,感觉把希望寄托给了计算机,何时结束,它决定!如果遇到高并发的请求,CPU必定不堪重负!那么作为一名久经沙场的老司机,到底该如何优化这个算法呢?
要优化算法,首先就要找到可优化点在哪里。上面代码的痛点是靠递归排除重复项,以达到“不信找不到不重复项”的目的。如果我们在获取数据的时候就排除已经获取过的,是不是就不可能重复了呢?说到这里,相信很多人已经想到一个方案:每次获取之后,都把该项从原数组中移除,这样下次获取时就不可能得到重复的项了。但是做过性能测试的文艺青年又怎能不知道,更新原数组的代价比递归获取还要高!我擦,那还说个毛线!别急,既然不能移除,那我们就不移除就是了。我们的目的并不是移除已有数据,而是不获取已有数据。而“不获取”就有两种做法了,一种是移除,一种是替换掉。于是推出了以下做法:每次获取之后,把数组的最后一项放到被获取的这一项的位置上,然后下次随机的时候忽略最后一位。见下图:
替换之后,再次随机取值的时候只考虑a到f也就是random(0,5)就行了,再一次取值以次类推。
理清了这个思路,再回过头来优化这个函数,可以得出如下代码:
function getRandomArray(list, total) { if (!list || !list.slice) return []; if (list.length <= total) return list; // 为了不改变原始数据,这里复制一份数组进行操作 var arr = list.slice(), result = [], len = list.length; while (result.length < total) { var index = Math.floor(Math.random() * (len - result.length)); result.push(arr[index]); arr[index] = arr[len - result.length]; } return result;}
现在看起来是不是优雅多了?在实现需求的同时,没有浪费一丁点CPU资源。
如有不同思路,欢迎留言讨论!
- 如何高效的提取随机数据
- 高效的MySql 随机读取数据
- SQL实现随机提取数据
- mysql 随机取数据 高效
- Sqlserver中百万数据随机提取的问题
- 在 MySQL中,从10 万条主键不连续的数据里随机取 3000 条,如何做到高效?
- 在 MySQL中,从10 万条主键不连续的数据里随机取 3000 条,如何做到高效?
- Javascript中如何高效的数据存取
- mysql如何随机获取数据的方法
- SQL/ACCESS/MYSQL随机提取数据
- ORACLE 提取N条随机数据
- oracle 提取数据 随机排序
- ActiveRecord 如何高效地获取随机 records
- 从1-N的范围内随机取出K个数,并且不能重复值,如何高效取出?
- 如何更高效的对首页数据的展示
- 6.2 ShellCode的高效提取技巧
- sql 如何提取某一字段记录的部分数据
- 如何使用ArcMap提取地图数据的坐标信息
- 【分享】iTOP4412开发板-Bluetooth移植文档
- Linux设置和查看环境变量
- PAT 乙级1004
- OpenSessionInView
- java桌面应用开发流程
- 如何高效的提取随机数据
- 【每日一课】2、java的发展历
- PAT-basic level-1002
- 7.0 CTS fail 项分析之google Issue (一)
- 平台设备总线
- block,inline和inline-block概念和区别
- es6 rest 参数
- 解决UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe5 in position 108: ordinal not in range(128
- oracle一个创建用户、创建表空间、授权、建表的完整过程