根据两个不同数组的值创建Array2D

时间:2018-11-15 16:45:15

标签: multidimensional-array f#

我在正确设置此代码时遇到问题。 Contour变量的结果应为Array2D 64x64,其中包含arr1乘arr2的轮廓数据。我将两个数组作为示例。语法错误表示最后一次let之后的块未完成。

type System.Random with
    /// Generates an infinite sequence of random numbers within the given range.
    member this.GetValues(minValue, maxValue) =
        Seq.initInfinite (fun _ -> this.Next(minValue, maxValue))

let cnt = 10000
let r = System.Random()
let arr1 = r.GetValues(1, 262144) |> Seq.take cnt
let arr2 = r.GetValues(1, 262144) |> Seq.take cnt

let datareso = 262144
let dispreso = 64
let bucketsiz = datareso / dispreso

let Contour = 
        let dat = Array2D.init dispreso dispreso (fun i j -> 0)
        for idx in 0 .. cnt-1 do
            let x = System.Math.Round(arr1.[idx] / bucketsiz)
            let y = System.Math.Round(arr2.[idx] / bucketsiz)
                       dat.[x, y] + 1
        dat

2 个答案:

答案 0 :(得分:2)

除了您遇到的错误之外,我还在您的代码中看到了其他一些初学者错误。我会为您列出所有内容。

首先,您要创建两个名为arr1arr2的序列,然后在循环中通过索引访问它们。我强烈怀疑您是说它们是数组,因为按索引访问序列是O(N)操作,而访问数组索引是O(1)。因此,您的循环现在是O(N ^ 2),应该是O(N)。要解决此问题,请在创建Array.ofSeqSeq.take cnt时在arr1之后向arr2添加一个呼叫:

let arr1 = r.GetValues(1, 262144) |> Seq.take cnt |> Array.ofSeq
let arr2 = r.GetValues(1, 262144) |> Seq.take cnt |> Array.ofSeq

第二,通过使用始终返回0的初始化函数调用Array2D.init来创建数组。有一种更快的方法:调用Array2D.zeroCreate。使用Array2D.init将调用您的函数dispreso * dispreso次,而Array2D.zeroCreate将消除所有这些函数调用。任何时候要将数组初始化为零(或初始化为数组中任何类型的默认值)时,请始终使用zeroCreate函数,因为它是迄今为止效率最高的。

下一步,此行不执行任何操作:

dat.[x, y] + 1

我假设您想做的是增加2D数组中位置x, y上存储的值。但是该行所做的是检索值并将其加1,并产生一个结果,该结果被丢弃,因为它没有存储在任何地方或未在任何计算中使用。 (您可能会在该行的编译器警告中说“类似此值已被有效忽略”,并告诉您对其进行修复)。您想要的是将该值存储回数组中,如下所示:

dat.[x, y] <- dat.[x, y] + 1

最后,导致“未完成的代码块”错误的原因是dat.[x, y] + 1行缩进得太远了,因此let y = ...行之后没有任何语句。这是F#中的语法错误:let语句后应该总有东西。只需使dat.[x, y] + 1行缩进即可获得正确的结果。

这是您的代码,所有这些错误均已纠正:

type System.Random with
    /// Generates an infinite sequence of random numbers within the given range.
    member this.GetValues(minValue, maxValue) =
        Seq.initInfinite (fun _ -> this.Next(minValue, maxValue))

let cnt = 10000
let r = System.Random()
let arr1 = r.GetValues(1, 262144) |> Seq.take cnt |> Array.ofSeq
let arr2 = r.GetValues(1, 262144) |> Seq.take cnt |> Array.ofSeq

let datareso = 262144
let dispreso = 64
let bucketsiz = datareso / dispreso

let Contour = 
        let dat = Array2D.zeroCreate dispreso dispreso
        for idx in 0 .. cnt-1 do
            let x = System.Math.Round(arr1.[idx] / bucketsiz)
            let y = System.Math.Round(arr2.[idx] / bucketsiz)
            dat.[x, y] <- dat.[x, y] + 1
        dat

答案 1 :(得分:0)

通过此行:

Value Hex RGB Name
    0 #000000 Black
    1 #000080 DarkBlue
    2 #008000 DarkGreen
    3 #008080 DarkCyan
    4 #800000 DarkRed
    5 #012456 DarkMagenta
    6 #EEEDF0 DarkYellow
    7 #C0C0C0 Gray
    8 #808080 DarkGray
    9 #0000FF Blue
   10 #00FF00 Green
   11 #00FFFF Cyan
   12 #FF0000 Red
   13 #FF00FF Magenta
   14 #FFFF00 Yellow
   15 #FFFFFF White

您的意思是这样的吗?

    dat.[x, y] + 1

我注意到该行中的文本中有一个奇怪的初始空格。