之前写一款小卡牌游戏时, 写过从数组中随机抽取X个数的方法(X小于数组长度);然后学习了 underscore 的 “sample” 方法,知道了最简单的实现法:
_.sample([1, 2, 3, 4, 5, 6]); => 4 _.sample([1, 2, 3, 4, 5, 6], 3); => [1, 6, 2]
以上,但如果我们小项目中不想导入一个undersocre.js。 该怎么办呢?目前想到的办法有两 分别是:
1.将该逻辑代码从 underscore.js 中抽离出来;
_.sample = function(obj, n, guard) { if (n == null || guard) { if (!isArrayLike(obj)) obj = _.values(obj); return obj[_.random(obj.length - 1)]; } return _.shuffle(obj).slice(0, Math.max(0, n)); };
以上可以看出,该方法依赖了 很多underscore.js的其他方法:
isArrayLike(obj) //判断参数是否为数组的全局函数表达式;
_.values(obj) //将对象值 变成数组
_.random(min, max) //返回 最大值、最小值中间的随机数(返回的都是整数)
_.shuffle(obj) //返回打乱顺序后的数组(或对象变成的数组)
要抽出这么一个方法,得连带的抽出underscore.js 四个方法,uderscore.js 考虑的情况跟代码复用做的是很不错,但 似乎不是我想要的。
我想要的方法不需要考虑 参数进来的是对象 还是 数组,也不需要拆分成那么多方法, 一个方法足矣!
2.自己重新写一个;
惯例,本文就第二点详细 的。。。。。。。 贴上代码! =_=
function arraySample(array, n){ var _result = []; var _index = 0; // 防止原数组被改变 var _arrayTemp = array.slice(0);
if (array == null || array.length == 0 || array.length < n){ return _result; } // 随机获取一个值 if (n == null){ _index = Math.floor(Math.random() * array.length); _result.push(array[_index]); }else{ // 随机获取N个值 for (var i = 0; i < n; i++){ _index = Math.floor(Math.random() * _arrayTemp.length); _result.push(_arrayTemp[_index]); // 删除该元素 _arrayTemp.splice(_index, 1); } } return _result; }
实现的关键点在于 Math.random() 、 Math.floor() 的灵活调用, 获得数组中的随机坐标, 然后进行处理;