2011-12-27 29 views
3

我需要定义一个int类型的矩阵。矩阵的一列或一行代表city,矩阵中的元素表示行城与列之城之间的distance。矩阵的维数可能会发生变化(我们可能会增加或删除城市),但它总是很小。用OCaml中的数组,列表或映射定义int的矩阵?

我犹豫之间int array arrayint list list并用map一个类型,其定义如下:

module MatOrd = struct 
    type t = string * string 
    let compare ((a, b): string * string) ((c, d) : string * string) = 
    if Pervasives.compare a c <> 0 
    then Pervasives.compare a c 
    else Pervasives.compare b d 
end 

module MatMap = Map.Make(MatOrd) 

然后int MatMap.t可以表示为int的矩阵。这个定义的一个优点是我可以直接写一个城市的名字作为矩阵的坐标。对于int array arrayint list list而言,我似乎必须记住坐标的含义......

此外,我们无法与数组进行模式匹配吗?例如,我们不能写:

match a_array with 
    [| first_element; the_rest_elements |] -> ... 

有我提到的优点和缺点,或不是,你建议哪种类型?

+0

你不能写'match a_array with [| first_element; the_rest_elements |] - > ...因为这不是你访问数组元素的方式。 'the_rest_elements'既不存在于内存中,也不具有类型系统中的类型。但是你可以很好地与数组进行模式匹配。 – 2011-12-27 08:14:19

回答

3

这种或那种类型的适用性真的取决于你用什么操作来实现它。你会用你的类型计算什么?

例如,您可能想要利用在某处执行的矩阵操作,例如min-plus multiplication,这可能会帮助您解决最短路径问题。在这种情况下,使用矩阵是有意义的,并且具有单独的功能string -> int,其从城市名称转换为矩阵坐标。另一方面,如果你只想要一个计算稀缺的数据存储,那么类似上面那样的Map类型可能更有意义。

很难给不知道你要计算什么非常有见地的答案,但对于你的建议:

  • 记住名单是不可改变的,因此int list list具有有限效用
  • ,如果你做两个维阵列,当心数组是可变的引用和做作相应处理,从而使后执行以下操作:

    let a = Array.make 3 0;; 
    let a = b;; 
    b.(0) <- 42;; 
    

    a.(0)等于42

    的语言,有一个热心的评价策略,使另一个需要注意的是,你不应该创建一个数组的方式如下:

    let m = Array.make 2 (Array.make 3 0);; 
    m : int array array = [|[|0; 0; 0|]; [|0; 0; 0|]|] 
    m.(0).(0) <- 1;; 
    - : unit =() 
    m;; 
    - : int array array = [|[|1; 0; 0|]; [|1; 0; 0|]|] 
    

    make呼叫被首先计算,并且相同的参考是由共享外部数组的三条 行。有关如何创建矩阵,请参阅the FAQ

顺便说一下,你可以做阵列模式匹配(在relevant manual section显示在页面底部的图案),但你必须把模式变量时要尊重你的阵列的尺寸。谢天谢地,你可以使用_,正如你所说,你的阵列的尺寸很小。

+0

一般来说,有很好的联系和合理的答案,但我不认为你的意思是在第二个要点中“通过名称传递”。 Ocaml永远不会使用“按名称传递”的语义。下面是关于“通过名称传递”语义的描述:http://www.cs.sfu.ca/~cameron/Teaching/383/PassByName.html此外,这是因为它们是而不是通过名称和相反,外部构造函数的参数是通过值传递的(因此只评估一次)näive2-d数组创建失败。 – 2011-12-27 10:50:04

+0

当然!更正以消除任何含糊不清/错误 – huitseeker 2011-12-27 11:13:21