问题
I try to get value by key from sorted map with comparator by value it returns 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
Expected: {:v 3}
Actual: nil
回答1:
You are creating a custom Comparator with compare that is being used in PersistentTreeMap (the type of tmap-sorted
) to lookup the value but your comparator never returns 0 which would mean that two objects are equal.
https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html
Caution should be exercised when using a comparator capable of imposing an ordering inconsistent with equals to order a sorted set (or sorted map). Suppose a sorted set (or sorted map) with an explicit comparator c is used with elements (or keys) drawn from a set S. If the ordering imposed by c on S is inconsistent with equals, the sorted set (or sorted map) will behave "strangely." In particular the sorted set (or sorted map) will violate the general contract for set (or map), which is defined in terms of equals.
If you modify your comparator to println
for debug you can see that when compare 3 to 3 you get 1 meaning they are not equal.
(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
So you need to fix your compare
function to work for equality
来源:https://stackoverflow.com/questions/42231882/sorted-map-returns-nil-value-for-existing-key