2

我开始从 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 中可用,我希望获得相同的功能。经过一番谷歌搜索后我无法找到它,所以我想我会在这里问。这是可用的还是我必须自己实现的功能?谢谢!

4

3 回答 3

2

您可以使用该random.shuffle软件包,它带有一个shuffle'功能。但是你需要一个随机生成器。

您还可以在 haskell wiki 上寻找进一步的解释:http ://www.haskell.org/haskellwiki/Random_shuffle

一旦你的列表被洗牌,你可以take n它的元素。

于 2013-08-07T14:29:00.560 回答
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.ApplicativeliftM2 (:) (return val) (sample (ct-1) (delete val xs))

但是,使用delete确实会对列表元素的类型产生Eq限制,因此如果需要避免这种情况,则必须在索引处拆分/合并。

于 2013-08-07T21:42:59.280 回答
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 中,尽管您可以生成随机种子,然后将其传递给函数。这段代码得到一个随机整数,确保它在列表的范围内。然后拆分列表并返回该数字,从而将其从列表中删除,然后递归直到不再需要数字。

于 2013-08-07T14:35:24.177 回答