OCaml-从一维数组到二维数组的转换

OCaml-从一维数组到二维数组的转换,ocaml,Ocaml,我试图在OCaml中将一维数组转换为二维数组 在测试我编写的函数时: # to_array2d [|1;2;3;1;2;4;1;2;5|];; 我得到了不正确的结果: int array array = [|[|1; 2; 5|]; [|1; 2; 5|]; [|1; 2; 5|]|] 正确的结果应该是: int array array = [|[|1; 2; 3|]; [|1; 2; 4|]; [|1; 2; 5|]|] 代码如下: let to_array2d (array1d: in

我试图在OCaml中将一维数组转换为二维数组

在测试我编写的函数时:

# to_array2d [|1;2;3;1;2;4;1;2;5|];;
我得到了不正确的结果:

int array array = [|[|1; 2; 5|]; [|1; 2; 5|]; [|1; 2; 5|]|]
正确的结果应该是:

int array array = [|[|1; 2; 3|]; [|1; 2; 4|]; [|1; 2; 5|]|]
代码如下:

let to_array2d (array1d: int array) : int array array = 
    let dim = int_of_float (sqrt (float (Array.length array1d))) in
        let array2d = Array.make dim (Array.make dim 0 ) in
            for i = 0 to (dim - 1) do 
                    for j = 0 to (dim - 1) do
                        array2d.(i).(j) <- (Array.get array1d (i * dim + j))
                    done
                done;
                array2d
;;
let to_array2d(array1d:int数组):int数组=
设dim=in中浮点(sqrt(float(Array.length array1d))的整数
将array2d=Array.make dim(Array.make dim 0)放入
对于i=0至(尺寸-1)do
对于j=0至(尺寸-1)do

array2d.(i)。(j)您创建的二维数组不正确
Array.make
将只复制第二个参数
dim
次。因此,您有一个指向同一数组的三个指针的数组。查看有关如何正确烹饪数组的更多详细信息。使用
Array.init
函数可以更好地编写您的特定案例

let to_array2d (array1d: int array) : int array array = 
  let dim = int_of_float (sqrt (float (Array.length array1d))) in
  Array.init dim (fun i -> Array.init dim (fun j -> array1d.(i * dim + j)))
尽管如此,我不喜欢
sqrt
ing长度的想法


关于这个问题的一个很好的解释可以在中找到。请参阅第68页(pdf第94页)。

您创建的二维阵列不正确
Array.make
将只复制第二个参数
dim
次。因此,您有一个指向同一数组的三个指针的数组。查看有关如何正确烹饪数组的更多详细信息。使用
Array.init
函数可以更好地编写您的特定案例

let to_array2d (array1d: int array) : int array array = 
  let dim = int_of_float (sqrt (float (Array.length array1d))) in
  Array.init dim (fun i -> Array.init dim (fun j -> array1d.(i * dim + j)))
尽管如此,我不喜欢
sqrt
ing长度的想法


关于这个问题的一个很好的解释可以在中找到。查看第68页(pdf第94页)。

详细说明@ivg的答案:
数组。make
将获取您给定的值,并将其放入新数组的所有元素中。对于具有结构的值(如数组),这意味着您最终将出现三次相同的值


要详细说明@ivg的答案:
Array.make
将获取您给它的值,并将其放入新数组的所有元素中。对于具有结构的值(如数组),这意味着您最终将出现三次相同的值


代码中的错误位置是

let b =
  Array.make dim (Array.make dim 0)
这不是你想要的。名称
b
不在代码中,但便于讨论。为了理解您看到的内容,让我们以以下等效方式重写此代码:

let b =
  let a = Array.make dim 0 in
  Array.make dim a
此代码生成一个长度为
dim
的数组,其条目均为
a
。这些不是
a
的副本,它们只是
a
的不同名称。用OCaml表示这一点的正确方法是说这些结构在物理上是相等的,
=
操作符测试物理上的相等性

# b.(0) == b.(1);;
true
物理相等是比更常见的
=
运算符测试的结构相等更强的关系。规定,给定两个物理上相等的可变结构,如
b.(0)
b.(1)
,对其中任何一个结构的修改也会影响另一个结构,或者换句话说:

val(=):'a->'a->bool
e1==e2
测试
e1
e2
的物理相等性。对于可变类型,如引用、数组、字节序列、具有可变字段的记录和具有可变实例变量的对象,
e1==e2
为真,当且仅当
e1
的物理修改也影响
e2
。在不可变类型上,
(==)
的行为依赖于实现;但是,可以保证
e1==e2
意味着比较
e1 e2=0

我们可以把这看作是一种正式的说法,即这两种结构“实际上是相同的”

如果您想调整代码的结构,可以利用
数组。make_matrix
函数生成新的二维数组。如果您厌倦了调试for循环中的错误,可以使用更为ocaml ish的解决方案:

let unpack dim a =
  let line i =
    Array.init dim (fun j -> a.(i*dim + j))
  in
  Array.init dim line

let to_array2d a =
  let dim = int_of_float (sqrt (float (Array.length array1d))) in
  unpack dim a
另请参见


    • 代码中的错误位置是

      let b =
        Array.make dim (Array.make dim 0)
      
      这不是你想要的。名称
      b
      不在代码中,但便于讨论。为了理解您看到的内容,让我们以以下等效方式重写此代码:

      let b =
        let a = Array.make dim 0 in
        Array.make dim a
      
      此代码生成一个长度为
      dim
      的数组,其条目均为
      a
      。这些不是
      a
      的副本,它们只是
      a
      的不同名称。用OCaml表示这一点的正确方法是说这些结构在物理上是相等的,
      =
      操作符测试物理上的相等性

      # b.(0) == b.(1);;
      true
      
      物理相等是比更常见的
      =
      运算符测试的结构相等更强的关系。规定,给定两个物理上相等的可变结构,如
      b.(0)
      b.(1)
      ,对其中任何一个结构的修改也会影响另一个结构,或者换句话说:

      val(=):'a->'a->bool
      e1==e2
      测试
      e1
      e2
      的物理相等性。对于可变类型,如引用、数组、字节序列、具有可变字段的记录和具有可变实例变量的对象,
      e1==e2
      为真,当且仅当
      e1
      的物理修改也影响
      e2
      。在不可变类型上,
      (==)
      的行为依赖于实现;但是,可以保证
      e1==e2
      意味着比较
      e1 e2=0

      我们可以把这看作是一种正式的说法,即这两种结构“实际上是相同的”

      如果您想调整代码的结构,可以利用
      数组。make_matrix
      函数生成新的二维数组。如果您厌倦了调试for循环中的错误,可以使用更为ocaml ish的解决方案:

      let unpack dim a =
        let line i =
          Array.init dim (fun j -> a.(i*dim + j))
        in
        Array.init dim line
      
      let to_array2d a =
        let dim = int_of_float (sqrt (float (Array.length array1d))) in
        unpack dim a
      
      另请参见