我编写了一个函数来对数组进行置乱,并映射一个数组来对每个数组进行不同的置乱,但是它们是以相同的方式被置乱的。
let rand = System.Random()
let shuffle (rand : System.Random)(array :int[] ) = let rng = new Random()
let mutable n = array.Length
while (n > 1) do
let k = rng.Next(n)
n <- n - 1
let temp = array.[n]
array.[n] <- array.[k]
array.[k] <- temp
array
let playsarray = shuffle rand
let scrambledarray = Array.map (fun x -> playsarray x )
let playsarra = fun (array : int[]) -> array |> playsarray
let smallarray = [1..10].ToArray()
let megaarray = Array.create 10 smallarray
let megarrayscrambled = megaarray |> scrambledarray
megarrayscrambled |> Seq.iter (fun y -> printfn "Ar: %A" y)运行代码后,所有10个数组在数据ej中都具有相同的顺序。
发布于 2019-07-23 03:16:42
您的代码有两个问题。
首先,您的shuffle函数接受一个rand参数,但实际上并没有使用它:在该函数中,您创建一个新的System.Random实例并使用它,而不是使用传入的实例。 constructor提到(在示例中)默认构造函数使用当前时间作为种子,因此如果快速地连续创建两个Random对象,它们将具有相同的种子,从而产生相同的值。要解决这个问题,您只需要停止在您的Random函数中创建一个新的shuffle实例,而是使用传入的实例(我将它从rand重命名为rng,以便您的其余代码不需要更改)。下面是修改后的shuffle函数(以及易于阅读的缩进:您不必在同一行上启动函数的第一行与=符号;您可以将其放在下一行,只需缩进一个缩进级别,即四个空格):
let shuffle (rng : System.Random) (array : int[]) =
let mutable n = array.Length // The number of items left to shuffle (loop invariant).
while (n > 1) do
let k = rng.Next(n) // 0 <= k < n.
n <- n - 1 // n is now the last pertinent index;
let temp = array.[n] // swap array[n] with array[k] (does nothing if k == n).
array.[n] <- array.[k]
array.[k] <- temp
array但是还不能解决您的问题,因为您也误解了Array.create的工作方式。它创建一个给定大小的数组,其中数组中的每个项都包含传入的值。也就是说,megarrayscrambled数组中的每个条目都包含对同一个smallarray的引用。如果您使用megarrayscrambled.[0].[0] <- 999,您会发现这改变了megarrayscrambled中的十个条目中的每一个条目,因为它们是相同的数组。
您真正想要的是使用Array.init,而不是Array.create。Array.init接受一个函数,并在您正在构建的数组中的每个项中运行该函数一次。这意味着,如果该函数返回[1..10].ToArray(),那么每次调用它时,它将返回一个不同的数组,因此您将得到所期望的结果。(顺便说一句,您可以通过执行[|1..10|]来创建一个数组,这就是我将在下面的示例代码中使用的)。
因此,只需将let megaarray行更改为:
let megaarray = Array.init 10 (fun _ -> [|1..10|])然后你应该看到你期待的结果。
顺便说一句,还有一个小细节:在一行中,您有Array.map (fun x -> playsarray x),但这等同于Array.map playsarray,它更容易阅读。
https://stackoverflow.com/questions/57156068
复制相似问题