F#中的采样:设置是否足够?

nic*_*las 2 f# set sampling

我有一系列项目,我想从中抽样.

我的印象是,Set会有一个好的结构来取样,在折叠中我会回复原始或修改后的元素,如果我想要替换不是,则将检索到的元素丢失.但是,似乎没有方法直接从Set检索元素.

有什么我想念的吗?或者我应该使用一组索引,以及一个随机开始的代理函数,position < Set.count直到它找到一个成员为止?

也就是说,沿着这条线

module Seq =
    let modulo (n:int) start = 
        let rec next i = seq { yield (i + 1)%n ; yield! next (i+1)}
        next start

module Array =
    let Sample (withReplacement:bool) seed (entries:'T array) = 
        let prng, indexes = new Random(seed), Set(Seq.init (entries |> Array.length) id)
        Seq.unfold (fun set  -> let N = set |> Set.count
                                let next = Seq.modulo N (prng.Next(N)) |> Seq.truncate N |> Seq.tryFind(fun i -> set |> Set.exists ((=) i))
                                if next.IsSome then
                                    Some(entries.[next.Value], if withReplacement then set else Set.remove next.Value set)
                                else
                                    None)
Run Code Online (Sandbox Code Playgroud)

编辑:积极跟踪我给出的内容,而不是跟踪我仍然可以提供的内容将使其更简单,更有效.

Pat*_*ald 5

对于无需替换的采样,您可以只置换源seq并采用您想要采样的许多元素

let sampleWithoutReplacement n s =
    let a = Array.ofSeq s
    seq { for i = a.Length downto 1 do
              let j = rnd.Next i
              yield a.[j]
              a.[j] <- a.[i - 1] }
    |> Seq.take n
Run Code Online (Sandbox Code Playgroud)

向样品与更换,只需选择从源SEQ随机元素的n倍

let sampleWithReplacement n s =
    let a = Array.ofSeq s
    Seq.init n (fun _ -> a.[rnd.Next(a.Length)])
Run Code Online (Sandbox Code Playgroud)

然而,这些可能不是具有大量数据集的最有效方法