Sort by arbitrary comparator

I have a map that looks like this:

user> (frequencies "aaabccddddee")
{\a 3, \b 1, \c 2, \d 4, \e 2}

And I would like to have a function that sorted key / value pairs according to the order that each character appears in the string that I would pass as an argument.

Something like that:

user> (somesort "defgcab" (frequencies "aaabccddddee"))
[[\d 4] [\e 2] [\c 2] [\a 3] [\b 1]]

(in the above example, "f" and "g" are not displayed on the map, and therefore are ignored. It is guaranteed that the string - "defgcab" in this example - must contain each character / key on the map)

The resulting collection does not matter much while it is sorted.

I have tried several things but cannot find a way to make this work.

+3
source share
4 answers

sort-by :

(defn sorter [coll] (zipmap coll (range)))

(sort-by (comp (sorter "defgcab") key) 
         (frequencies "aaabccddddee"))

;=> ([\d 4] [\e 2] [\c 2] [\a 3] [\b 1])

: : , , :

(defn map-sorter [coll]
  (let [order (zipmap coll (range))]
    (fn [a b]
      (compare (order a) (order b)))))

(into (sorted-map-by (map-sorter "defgcab"))
      (frequencies "aaabccddddee"))

;=> {\d 4, \e 2, \c 2, \a 3, \b 1}
+6
(defn somesort [str st] 
    (filter (fn [[k v]] v ) (map (fn [c] [c (get st c)]) str)) )

:

  • , , nil
+2

Ankur, for, , , :

(defn somesort [str st] 
    (for [c str :let [v  (get st c)] :when v] [c v]))

, .

, . , , , -, .

+2

You can also use findone that returns [k v]with map:

(let [fs (frequencies "abbccc")]
  (map #(find fs %) "defgcab")
+1
source

All Articles