【问题标题】:How to add elements to a Map?如何向地图添加元素?
【发布时间】:2019-12-31 23:49:35
【问题描述】:

我的节点类型如下:

type position = float * float
type node = position

我编写这些模块是为了在我的地图中使用节点作为键:

module MyMap =
  struct
    type t = node
    let compare n1 n2 =
    if n1 = n2 then 1
    else 0
  end

module Dist = Map.Make(MyMap)

然后我创建了一个空地图:

let mapTest = Dist.empty;;
let mapTest = Dist.add (1.,1.) 1. mapTest;;

我得到这样的地图长度:

Dist.cardinal mapTest;;
- : int = 1

我尝试添加另一个元素:

let mapTest = Dist.add (2.,2.) 2. mapTest;;

但是当我使用 Dist.cardinal mapTest 时,我的 Map 长度仍然为 1

更令人惊讶的是,当我运行时:

Dist.find (1.,1.) mapTest;;
- : float = 2.

所以现在我对发生了什么或我做错了什么一无所知。

我的目标是能够使用地图、添加绑定等。

有什么想法吗?

谢谢

【问题讨论】:

    标签: dictionary ocaml


    【解决方案1】:

    compare 函数的行为与预期不同:当 n1 和 n2 相等时,它应该返回 0,否则如果 n1 大于 n2,则返回 1,否则返回 -1。

    以下代码将解决该问题:

    module MyMap =
      struct
      type t = node
      let compare (a1,b1) (a2,b2) =
        if a1 > a2 then 1 
         else if a1 < a2 then -1
         else if b1 > b2 then 1
           else if b1 < b2 then -1 
    
           else 0
      end
    

    【讨论】:

    • 那些比较运算符在浮点数上不是总的,希望 OP 不使用 NaN。
    【解决方案2】:
    let compare n1 n2 =
        if n1 = n2 then 1
        else 0
    

    您似乎误解了compare 的行为方式。这是the documentation of OrderedTypecompare的描述:

    这是一个双参数函数f,如果e1e2 相等,则f e1 e2 为零,如果e1 小于e2,则f e1 e2 严格为负,如果e1 大于e2,则f e1 e2 是严格正数。

    因此,按照您定义它的方式,n1 将被视为大于 n2,如果 n1 = n2,否则 n1 将被视为等于 n2。这不符合您对比较函数所期望的任何规则:一个键不被认为等于它自己,并且“n1 大于 n2”可以(实际上总是)在与“n2 大于 n1”同时。因此,地图将无法以合理的方式运行。

    假设您想认为一个节点等于另一个节点当且仅当它们包含相同顺序的相同值时,您可以使用 Stdlib.compare 定义 compare

    【讨论】:

      【解决方案3】:

      这不是你应该编写compare 函数的方式。

      引用手册:

      对键的总排序函数。这是一个两个参数 如果键 e1 和 e2 相等,函数 f 使得 f e1 e2 为零, 如果 e1 小于 e2,则 f e1 e2 为严格负数,并且 f e1 e2 为 如果 e1 大于 e2,则严格为正。例子:一个合适的 排序函数是通用的结构比较函数 比较。

      所以你的比较函数应该是:

      let compare n1 n2 =
          if n1 < n2 then -1
          else if n1 > n2 then 1
          else 0
      

      请注意,在浮点数上,比较很奇怪。首先,四舍五入使一些数字看起来不等于。其次,更糟糕的是,标准比较并不完整(它们总是在 NaN 上返回 false)。

      谢天谢地,您可以信任标准的compare 函数来解决后一个问题:

      let compare (n1:t) n2 = Stdlib.compare n1 n2
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-18
        • 2017-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多