繁体   English   中英

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

[英]How to Generate A Specific Number of Random Indices for Array Element Removal 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万个元素的源数组。

我不会为此提供F#代码(因为我不知道F#...),但是我将描述您应该使用的方法/算法。

基本上,您想要做的是从给定列表list选择n随机元素。 这可以用伪代码完成:

chosen = []
n times:
    index = rng.upto(list.length)
    elem = list.at(index)
    list.remove-at(index)
    chosen.add(elem)

应该使用源列表中的所有可能的索引填充list变量,然后当从该索引列表中选择n随机值时,您将具有随机的,不同的索引,您可以根据需要进行任何操作,包括打印值,删除值,用价值观淘汰自己,等等。

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

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

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

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]

如果您需要一组与数组相比大小可忽略的索引,那么您正在做的事情应该没问题。 否则,请考虑对Knuth-Fisher-Yates随机播放进行变体处理,以随机排列1 .. n获得第一个i元素:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM