sorted-map返回现有密钥的nil值

时间:2017-02-14 16:57:42

标签: clojure

我尝试通过排序地图中的键获取值,使用比较器按值返回nil

(def tmap {1 {:v 1} 2 {:v 2} 3 {:v 3}})

(def tmap-sorted
  (apply sorted-map-by
         #(let [val-comp (- (compare
                             (get-in tmap [%1 :v])
                             (get-in tmap [%2 :v])))]
            (if (= val-comp 0)
              1
              val-comp))
         (flatten (vec tmap))))
; => {3 {:v 3} 2 {:v 2} 1 {:v 1}}

(get tmap-sorted 3)
;=> nil

预期:{:v 3}

实际:nil

1 个答案:

答案 0 :(得分:5)

您正在使用Comparator创建一个自定义compare PersistentTreeMaptmap-sorted的类型)来查找值,但您的比较器永远不会返回0意味着两个对象是平等的。

https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html

  

当使用能够强加与equals不一致的排序的比较器来排序有序集(或有序映射)时,应该小心。假设带有显式比较器c的有序集(或有序映射)与从集合S中绘制的元素(或键)一起使用。如果由S对S施加的排序与equals不一致,则排序集(或有序映射)将表现得“奇怪”。特别是有序集(或有序映射)将违反集合(或映射)的一般契约,它以等于的方式定义。

如果您将比较器修改为println进行调试,您可以看到,当将 3 3 进行比较时,您会得到 1 含义他们不平等。

(def tmap {1 {:v 1} 2 {:v 2} 3 {:v 3}})
(def tmap-sorted (apply
                  sorted-map-by
                  #(let [val-comp
                         (- (compare
                             (get-in tmap [%1 :v])
                             (get-in tmap [%2 :v])))
                         ret (if (= val-comp 0)
                               1
                               val-comp)]
     (println "%1: " %1 " %2: " %2 " ret=" ret)
     ret)
                        (flatten (vec tmap))))


(get tmap-sorted 3)
;; %1:  3  %2:  2  ret= -1
;; %1:  3  %2:  3  ret= 1

(get tmap-sorted 1) 
;; %1:  1  %2:  2  ret= 1
;; %1:  1  %2:  1  ret= 1

因此,您需要修复compare函数以实现平等