Search code examples
clojure

Sorting a vector of maps by a value in map against a vector of those values - Clojure


We have sort-by in clojure to sort values against a vector or map.

For example, if I have a vector that I want to sort against:

(def ^:const sort-numbers ["one" "two" "three" "four" "five"])

And I have this random vector with disordered values, something like:

(def numbers ["two" "three" "one" "four"])

Now, they could be sorted by:

(sort-by #(.indexOf sort-numbers %) numbers)

Again, now I have this vector of maps:

(def numbers-map [{:one 1 :two 2 :three 3} 
                  {:one 4 :two 4 :three 3}
                  {:one 3 :two 2 :three 1}])

If I want to sort the numbers-map by the value of the key :one against all the maps in the vector,

(sort-by :one numbers-map)

would do, and it would give me the following result:

({:one 1, :two 2, :three 3} {:one 3, :two 2, :three 1} {:one 4, :two 4, :three 3})

Now, what I need is a combination of these. That is, I need to sort the numbers-map by the value of the key :one, but I don't want them to be auto-sorted, but rather sort them against a specified vector of all possible values of :one that I already have somewhere.

How can that be achieved?


Solution

  • This allows you to do that

    (def numbers-maps [{:one 1 :two 2 :three 3} 
                       {:one 4 :two 4 :three 3}
                       {:one 3 :two 2 :three 1}])
    
    (def sort-numbers [4 3 2 1])
    
    (sort-by #(.indexOf sort-numbers (:one %))
             numbers-maps)
    
    ({:one 4, :two 4, :three 3}
     {:one 3, :two 2, :three 1}
     {:one 1, :two 2, :three 3})
    

    Here is another example:

    (def numbers-maps [{:one 6, :two 9, :three 9}
                       {:one 9, :two 9, :three 8}
                       {:one 7, :two 6, :three 2}
                       {:one 4, :two 4, :three 5}
                       {:one 9, :two 1, :three 5}
                       {:one 1, :two 8, :three 8}
                       {:one 8, :two 3, :three 9}
                       {:one 8, :two 4, :three 5}
                       {:one 4, :two 8, :three 1}
                       {:one 5, :two 1, :three 1}])
    
    (def one-values [10 5 1 2 4 3])
    
    (sort-by #(.indexOf one-values (:one %))
             numbers-maps)
    
    ({:one 6, :two 9, :three 9}
     {:one 9, :two 9, :three 8}
     {:one 7, :two 6, :three 2}
     {:one 9, :two 1, :three 5}
     {:one 8, :two 3, :three 9}
     {:one 8, :two 4, :three 5}
     {:one 5, :two 1, :three 1}
     {:one 1, :two 8, :three 8}
     {:one 4, :two 4, :three 5}
     {:one 4, :two 8, :three 1})