2017-10-30 12 views
0

ソートによって、私は、ネストされたClojureのマップを持っている:のClojure:ネストされたマップのカスタムコンパレータ

{ 
    :1 { 
    :priority "Medicore" 
    :somekey "SomeValue" 
    }, 
    :2 { 
    :priority "Enormous" 
    :somekey "SomeValue" 
    }, 
    :3 { 
    :priority "Weeny" 
    :somekey "SomeValue" 
    } 
} 

私の目標は「最高」の優先順位をマップからsomekeyの値を取得することです。外部マップには、3つの優先順位のいずれかを持つ要素が0〜n個含まれます。利用可能な優先度が最も高いエントリが複数ある場合は、いずれかを取っても問題ありません。

その他のSOの質問を調査した後、この問題を解決するにはsort-by機能を使用することをお勧めします。しかし私のpriorityは自然にソートされていないので、カスタムコンパレータを用意しなければならないでしょう。

これは可能ですか?私のアプローチは私の目標にとっても正しいものですか?

答えて

1

sort-byを使用するには、注文または優先順位の値を指定する必要があります。マップを比較するカスタムコンパレータを実装するか、並べ替えに使用するキーを計算するsort-byのkeyfnを定義することができます。 keyfnの解は以下の通りです。 keyfnリターンだけを使用すると、コンパレータを実装するよりも、要件に匹敵する同等の値が簡単に得られます。 Comparators Guideをご覧ください。

私たちは、その数値表現に文字列の優先度を変換する機能の定義を開始:

(let [priorities {"Medicore" 0 
        "Enormous" 1 
        "Weeny" 2}] 
    (defn priority->num [p] 
    (if-let [num (priorities p)] 
     num 
     (throw (IllegalArgumentException. (str "Unknown priority: " p)))))) 

(priority->num "Enormous") 
;; => 1 

今、私たちは、各マップの最大の優先度を計算する必要があります。

(defn max-priority-num [m] 
    (->> m 
     (vals) 
     (map (comp priority->num :priority)) 
     (apply max))) 

(max-priority-num {:1 {:priority "Medicore" :somekey "SomeValue"} 
        :2 {:priority "Enormous" :somekey "SomeValue"} 
        :3 {:priority "Weeny" :somekey "SomeValue"}}) 
;; => 2 

今、私たちは最終的にsort-byを使用することができます:

(def m1 {:1 {:priority "Medicore" :somekey "SomeValue"} 
     :2 {:priority "Medicore" :somekey "SomeValue"} 
     :3 {:priority "Weeny" :somekey "SomeValue"}}) 

(def m2 {:1 {:priority "Medicore" :somekey "SomeValue"} 
     :2 {:priority "Enormous" :somekey "SomeValue"} 
     :3 {:priority "Weeny" :somekey "SomeValue"}}) 

(def m3 {:1 {:priority "Medicore" :somekey "SomeValue"} 
     :2 {:priority "Medicore" :somekey "SomeValue"} 
     :3 {:priority "Medicore" :somekey "SomeValue"}}) 

(sort-by max-priority-num [m1 m2 m3]) 
;; => 
({:1 {:priority "Medicore", :somekey "SomeValue"}, 
    :2 {:priority "Medicore", :somekey "SomeValue"}, 
    :3 {:priority "Medicore", :somekey "SomeValue"}} 
{:1 {:priority "Medicore", :somekey "SomeValue"}, 
    :2 {:priority "Medicore", :somekey "SomeValue"}, 
    :3 {:priority "Weeny", :somekey "SomeValue"}} 
{:1 {:priority "Medicore", :somekey "SomeValue"}, 
    :2 {:priority "Enormous", :somekey "SomeValue"}, 
    :3 {:priority "Weeny", :somekey "SomeValue"}}) 
+0

これは 'sort-by'よりも' max-key'ではずっと簡単です。 – amalloy

+0

右@amalloy、私はOPを見落とした、すべての要素がソートされていない最大要素を取得したい! (max-key max-priority-num m1 m2 m3) 'または'(max-key max-priority-num mapsを適用する)の代わりに '(max-key-max-priority-num [m1 m2 m3] ) 'より良いでしょう。 –

関連する問題