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

Evg*_*nov 3 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
Run Code Online (Sandbox Code Playgroud)

预期: {:v 3}

实际: nil

Sco*_*ott 5

您正在创建一个自定义Comparator,compare用于PersistentTreeMap(类型tmap-sorted)查找值,但您的比较器永远不会返回0,这意味着两个对象相等.

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

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

如果您将比较器修改println为调试,您可以看到,当比较33时,您得到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
Run Code Online (Sandbox Code Playgroud)

所以你需要修复你的compare功能以实现平等