【问题标题】:How to Generate A Specific Number of Random Indices for Array Element Removal F#如何为删除数组元素 F# 生成特定数量的随机索引
【发布时间】:2013-07-03 18:49:30
【问题描述】:

所以 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 万个元素的源数组。

【问题讨论】:

    标签: arrays random f#


    【解决方案1】:

    如果您需要一组与数组相比大小可以忽略不计的索引,那么您正在做的事情应该没问题。否则,请考虑对 Knuth-Fisher-Yates shuffle 进行变体,以获得随机排列为 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
    

    【讨论】:

      【解决方案2】:

      我不会为此提供 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 随机值时,您将拥有随机的、不同的索引,您可以随心所欲地做任何事情,包括打印值、删除值、用值敲自己等等……

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          【解决方案4】:
          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]
          

          【讨论】:

          • 这会随着 max 接近计数而分解。
          • 如果您的意思是性能下降,是的,确实如此。但这是一个适用于许多情况的简单解决方案。
          • 这是一个不错的解决方案,但性能似乎是 OP 的关键问题。
          猜你喜欢
          • 2023-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-23
          • 1970-01-01
          • 1970-01-01
          • 2016-05-20
          相关资源
          最近更新 更多