より長いリストから、置き換えなしでランダムなサンプルを取得する必要があります (各要素はサンプル内で 1 回だけ発生します)。以下のコードを使用していますが、知りたいのですが:
- これを行うライブラリ関数はありますか?
- このコードを改善するにはどうすればよいですか? (私はHaskell初心者なので、ライブラリ関数があってもこれは役に立ちます)。
サンプリングの目的は、サンプルの分析から得られた結果を母集団に一般化できるようにすることです。
import System.Random
-- | Take a random sample without replacement of size size from a list.
takeRandomSample :: Int -> Int -> [a] -> [a]
takeRandomSample seed size xs
| size < hi = subset xs rs
| otherwise = error "Sample size must be smaller than population."
where
rs = randomSample seed size lo hi
lo = 0
hi = length xs - 1
getOneRandomV g lo hi = randomR (lo, hi) g
rsHelper size lo hi g x acc
| x `notElem` acc && length acc < size = rsHelper size lo hi new_g new_x (x:acc)
| x `elem` acc && length acc < size = rsHelper size lo hi new_g new_x acc
| otherwise = acc
where (new_x, new_g) = getOneRandomV g lo hi
-- | Get a random sample without replacement of size size between lo and hi.
randomSample seed size lo hi = rsHelper size lo hi g x [] where
(x, g) = getOneRandomV (mkStdGen seed) lo hi
subset l = map (l !!)