F# 集合中的随机元素<string>

F# Random elements from a set<string>

我正在从事一个项目,该项目要求我编写一个函数,该函数 select 从集合中指定数量的随机元素。然后将这些元素映射到一个变量以供以后比较。

所以在我的场景中,我必须 select 任何给定集合的 5%。

let rec randomSet (a:Set<string>) =
let setLength = (a.Count / 100) * 5

let list = []
let rand = System.Random
if set.Length <> setLength then
    // some code will go here
    randomSet setLength eIDS
else
    set

^请批评我的代码,我用 F# 编码才一周。

我试过递归地做,但我觉得这是错误的方法。我试过其他方法,但他们使用.take函数,因此每次返回的集合都是一样的。

有什么想法吗?我不是在一个集合中的 1 个元素之后,我是在任何集合中的 5% 之后。

这不是同一个问题:

如果你认为是,请说明。

有多种方法可以做到这一点。根据输入中的元素数量和您要选择的项目数量,不同的策略可能更有效。

可能最简单的方法是按随机数对输入进行排序,然后使用take得到所需的元素个数:

let data = [| 0 .. 1000 |]

let rnd = System.Random()

data 
|> Seq.sortBy (fun _ -> rnd.Next())
|> Seq.take 50

这将对序列进行随机排序(这对于大型序列来说可能会很慢),但是它会精确地获取您想要的元素数量(与 Mark 的解决方案不同,它将 return 大约 5% 的项目) .

如果你想 select 从一个大列表中选择一个小数字,最好随机生成索引(确保没有重复项),然后根据索引进行直接查找。

因为 Set<'a> 实现了 Seq<'a>,这个问题实际上是 的重复,你需要做的就是洗牌,取前 5 个% 元素,并将其放回集合中。

不过,为了好玩,这里有另一个解决方案。如果您需要选择 5%,那么首先定义一个谓词 returns true 只有 5% 的时间被调用:

let r = System.Random ()
let fivePercent _ = r.NextDouble () < 0.05

您现在可以使用该谓词过滤您的集合:

let randomlySelectedSubset = stringSet |> Seq.filter fivePercent |> set