0

所以 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

4 回答 4

1

如果您需要一组与数组相比大小可以忽略不计的索引,那么您正在做的事情应该没问题。否则,考虑做一个Knuth-Fisher-Yates 洗牌的变体,以获得i1 .. 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
于 2013-07-03T19:58:59.300 回答
0

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

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

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

于 2013-07-03T19:04:39.473 回答
0

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

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

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

您的list变量应填充源列表中所有可能的索引,然后当您n从该索引列表中选择随机值时,您将拥有随机的、不同的索引,您可以使用它们做任何您想做的事情,包括打印值、删除值、敲击自己的价值观等等......

于 2013-07-03T18:56:27.943 回答
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]
于 2013-07-03T19:34:17.947 回答