[英]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.