Order a list of 2-tuple (x,y) into a sorted-map of sets in Clojure
我正在尝试使用功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | (def in '([1 9] [1 8] [1 7] [2 1] [2 2] [2 3] [2 1] [2 2] [2 3] [2 1] [2 2] [2 3])) (def out (into (sorted-map) {1 (sorted-set 9 8 7) 2 (sorted-set 1 2 3)})) (defn list-of-xy->sorted-map-of-sorted-sets [list-of-xy] "Take a list (or lazy-seq) of 2-tuple and return a sorted-map of sorted-sets" (reduce ????? list-of-xy)) ; should return true (= (list-of-xy->sorted-map-of-sorted-sets in) out) |
到目前为止,我尝试分两个步骤创建
1 2 3 4 5 6 7 8 9 10 11 12 | (def int1 (group-by #(first %) in)) ;=> { 1 [[1 9] [1 8] [1 7]], ; 2 [[2 1] [2 2] [2 3] [2 1] [2 2] [2 3] [2 1] [2 2] [2 3]]} (def int2 (flatten (map #(let [[x xys] %] (list x (sorted-set (map last xys)))) int1))) ;=> (1 #{7 8 9} 2 #{1 2 3}) ; <-- this is not a sorted-map (yet!) |
有什么更好的方法来转换以性能为优先的
BTW
@Ankur答案被接受。 到目前为止,这是更快的解决方案。
对于我的实际问题,@ amalloy解决方案(+1)中的
1 2 3 4 | (fn [a [x y]] (if-not (get-in a [x y]) (update-in a [x] conj y) (reduced a))) |
1 2 3 4 | (= out (into (sorted-map) (map (fn [[k v]] [k (apply sorted-set (map second v))]) (group-by first in)))) |
让我知道这是否通过了您的性能测试:)。
1 2 3 4 5 6 | (defn list-of-xy->sorted-map-of-sorted-sets [list-of-xy] (let [conj (fnil conj (sorted-set))] (reduce (fn [acc [x y]] (update-in acc [x] conj y)) (sorted-map) list-of-xy))) |