如何为数组元素删除生成特定数量的随机索引F#

时间:2013-07-03 18:49:31

标签: arrays random f#

所以sCount是源数组中元素的数量,iCount是我想要删除的元素数。

let indices = Array.init iCount (fun _ -> rng.Next sCount) |> Seq.distinct |> Seq.toArray |> Array.sort

上述方法的问题是我需要专门删除iCount索引,但这并不能保证。

我尝过像

这样的东西
while indices.Count < iCount do
    let x = rng.Next sCount
    if not (indices.Contains x) then
        indices <- indices.Add x

以及其他一些类似的事情......

我尝试的每一种方式都非常缓慢 - 我正在处理大小高达2000万个元素的源数组。

4 个答案:

答案 0 :(得分:0)

我不会给你F#代码(因为我不知道F#...),但我会描述你应该使用的方法/算法。

基本上,您要做的是选择给定列表n的{​​{1}}个随机元素。这可以用伪代码完成:

list

您的chosen = [] n times: index = rng.upto(list.length) elem = list.at(index) list.remove-at(index) chosen.add(elem) 变量应填充源列表中的所有可能索引,然后当您从索引列表中选择list个随机值时,您可以执行随机,不同的索引无论你想要什么,包括印刷价值,去除价值,用价值观等等......

答案 1 :(得分:0)

是iCount更接近数组的大小还是更接近0?这将改变您将使用的算法。

如果接近0,则跟踪先前生成的数字并检查是否已生成其他数字。

如果更接近数组的大小,则使用@feralin

所述的方法

答案 2 :(得分:0)

let getRandomNumbers =
  let rand = Random()
  fun max count -> 
    Seq.initInfinite (fun _ -> rand.Next(max))
    |> Seq.distinct
    |> Seq.take count

let indices = Array.init 100 id
let numToRemove = 10

let indicesToRemove = getRandomNumbers (indices.Length - 1) numToRemove |> Seq.toList
> val indicesToRemove : int list = [32; 38; 26; 51; 91; 43; 92; 94; 18; 35]

答案 3 :(得分:0)

如果您需要一组与数组相比可忽略不计的索引,那么您所做的事情应该没问题。否则,请考虑对Knuth-Fisher-Yates shuffle进行变体,以便以1的随机排列方式获取第一个i元素.n:

let rndSubset i n =
    let arr = Array.zeroCreate i
    arr.[0] <- 0
    for j in 1 .. n-1 do
        let ind = rnd.Next(j+1)
        if j < i then arr.[j] <- arr.[ind]
        if ind < i then arr.[ind] <- j
    arr