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

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))

または、 andControl.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 モナドにいる必要がありますが、ランダムなシードを生成してから関数に渡すことはできます。このコードはランダムな int を取得し、それがリストの境界内にあることを確認します。次に、リストを分割してその番号を返すため、リストから削除してから、番号が不要になるまで再帰します。

于 2013-08-07T14:35:24.177 に答える