我开始从Ruby背景学习Haskell。我希望能从列表中获得任意数量的项目:
sample [1,2,3,4,5,6,7,8,9,10]
=> 7
sample 3 [1,2,3,4,5,6,7,8,9,10]
=> [4,2,9]
这在Ruby中可用,我希望获得相同的功能。我在google搜索后找不到它,所以我想我会在这里问。这是可用的还是我必须自己实现的功能?谢谢!
答案 0 :(得分:2)
您可以使用带有shuffle'
功能的random.shuffle
包。但是你需要一个随机发生器。
您还可以查看有关haskell wiki的更多说明:http://www.haskell.org/haskellwiki/Random_shuffle
一旦您的列表被随机播放,您可以take n
个元素。
答案 1 :(得分:1)
基于样本http://ruby-doc.org/core-2.0/Array.html的代码,它在数组中选择n个随机索引,我想出了以下内容:
import System.Random
import Data.List
import Control.Applicative
sample1 xs = do
let l = length xs - 1
idx <- randomRIO (0, l)
return $ xs !! idx
sample 0 xs = return []
sample n xs = do
let l = min n (length xs)
val <- sample1 xs
(:) <$> (pure val) <*> (sample (l-1) (delete val xs))
或者,您可以使用Control.Monad
代替Control.Applicative
和liftM2 (:) (return val) (sample (ct-1) (delete val xs))
使用delete
确实会对列表元素的类型产生Eq
约束,因此如果需要避免,则必须在索引处进行拆分/合并。
答案 2 :(得分:0)
代码:
import System.Random
sample :: Int -> [a] -> IO [a]
sample count lst = go count lst []
where go 0 _ acc = return acc
go count xs acc = do
rnd <- randomIO :: IO Int
let ind = rnd `rem` (length xs)
(beg, (r:rs)) = splitAt ind xs
go (count-1) (beg ++ rs) (r : acc)
由于随机数生成不纯,您需要在IO monad中,尽管您可以生成随机种子然后将其传递给函数。此代码获取随机int,确保它在列表的边界内。然后拆分列表并返回该数字,从而将其从列表中删除,然后递归,直到不再需要数字为止。