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