首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >F#为什么在将函数映射为对数组中的每个数组进行置乱时,数组没有以不同的方式进行置乱

F#为什么在将函数映射为对数组中的每个数组进行置乱时,数组没有以不同的方式进行置乱
EN

Stack Overflow用户
提问于 2019-07-23 03:00:52
回答 1查看 53关注 0票数 3

我编写了一个函数来对数组进行置乱,并映射一个数组来对每个数组进行不同的置乱,但是它们是以相同的方式被置乱的。

代码语言:javascript
复制
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中都具有相同的顺序。

  • Ar: 5;1;7;2;8;10;6;3;9;4
  • Ar: 5;1;7;2;8;10;6;3;9;4
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-23 03:16:42

您的代码有两个问题。

首先,您的shuffle函数接受一个rand参数,但实际上并没有使用它:在该函数中,您创建一个新的System.Random实例并使用它,而不是使用传入的实例。 constructor提到(在示例中)默认构造函数使用当前时间作为种子,因此如果快速地连续创建两个Random对象,它们将具有相同的种子,从而产生相同的值。要解决这个问题,您只需要停止在您的Random函数中创建一个新的shuffle实例,而是使用传入的实例(我将它从rand重命名为rng,以便您的其余代码不需要更改)。下面是修改后的shuffle函数(以及易于阅读的缩进:您不必在同一行上启动函数的第一行与=符号;您可以将其放在下一行,只需缩进一个缩进级别,即四个空格):

代码语言:javascript
复制
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.createArray.init接受一个函数,并在您正在构建的数组中的每个项中运行该函数一次。这意味着,如果该函数返回[1..10].ToArray(),那么每次调用它时,它将返回一个不同的数组,因此您将得到所期望的结果。(顺便说一句,您可以通过执行[|1..10|]来创建一个数组,这就是我将在下面的示例代码中使用的)。

因此,只需将let megaarray行更改为:

代码语言:javascript
复制
let megaarray = Array.init 10 (fun _ -> [|1..10|])

然后你应该看到你期待的结果。

顺便说一句,还有一个小细节:在一行中,您有Array.map (fun x -> playsarray x),但这等同于Array.map playsarray,它更容易阅读。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57156068

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档