# sampleSize
# Description
从 array(集合)中获得 n 个随机元素。
# Params
(array, n)
# Return
Array
# Depend
import copyArray from './.internal/copyArray.js'
import slice from './slice.js'
# Code
function sampleSize(array, n) {
n = n == null ? 1 : n
const length = array == null ? 0 : array.length
if (!length || n < 1) {
return []
}
n = n > length ? length : n
let index = -1
const lastIndex = length - 1
const result = copyArray(array)
while (++index < n) {
const rand = index + Math.floor(Math.random() * (lastIndex - index + 1))
const value = result[rand]
result[rand] = result[index]
result[index] = value
}
return slice(result, 0, n)
}
# Analyze
首先是参数合法化的处理
n = n == null ? 1 : n const length = array == null ? 0 : array.length if (!length || n < 1) { return [] } n = n > length ? length : n
如果 n 没有传入或者 n 为
null
,则 n 取 1然后判断了 数组的合法性,如果
length
为假值,或者n < 1
,则返回空数组然后对 n 进行了处理,这里其实就相当于
Math.max(n, length)
,在这其中取最大值接着是随机数组的处理
let index = -1 const lastIndex = length - 1 const result = copyArray(array) while (++index < n) { const rand = index + Math.floor(Math.random() * (lastIndex - index + 1)) const value = result[rand] result[rand] = result[index] result[index] = value }
这里的思路是这样的 我们要取一个随机的值,有可能要改变原数组,所以首先 copy 一份
将随机的值 放到数组的 index 位置,将 index 的值 放到 随机索引的位置,这样一来就完成了随机值的获取
但是这个过程对于 索引的随机就有要求了
这里随机的索引是这么处理的
const rand = index + Math.floor(Math.random() * (lastIndex - index + 1))
通过
index
加上Math.random() * (lastIndex - index + 1)
的值,这样的话已经遍历过的index
是不会在出现的,只会对剩余的数组元素进行随机获取,和上述的 思路是一致的最后通过
slice
进行截取,拿到结果
# Example
console.log(sampleSize([1,2,3,4,5,6,7], 3)) // [ 6, 7, 3 ]
如果 传入的 n 大于或者等于数组的长度,则最终的结果是 打乱数组的顺序