2

私は、各値に別のマップの関数を適用することによって、clojureハッシュマップを変換する方法を考え出そうとしています。これが私がこれまでに持っているものです:

(defn transform-map [m fm]
  (into {} (for [[k v] m]
    (let [mfn (get fm k identity)] [k (mfn v)])))

(def m {:a 0 :b 0 :c 0 :d 0})
(def fm {:a inc :b dec :c identity})
(transform-map m fm)  ;=> {:a 1, :b -1, :c 0, :d 0}

これは問題なく機能しますが、各関数がキーの現在の値である単一の引数を取る場合に限ります。同じキーの値以外の値を使用する関数を関数マップに配置したい場合はどうなりますか?たとえば、キーの合計をキーに入れたいと:a:bましょ:dう。

私は次のようなことを試すことができます:

(assoc fm :d (fn[a b] (+ a b)))

transform-mapしかし、関数呼び出しで適切な引数を使用するように関数を変更する方法はありますか?

4

2 に答える 2

4

関数を分解し、それらが変換マップにどのように適用できるかを提案します。以下はそれを示す例です:

;; functions which take some params and return a result
(defn sub [a b] (- a b))
(defn add [a b] (+ a b))

;; data map
(def data {:a 5 :b 4 :c 3})

;; transformation map key => output key, value is vector of function
;; to apply and the params that function will take from the data map
(def transformations {:a [inc :a]
                      :b [dec :b]
                      :c [add :a :b]
                      :d [sub :b :c]})

; The transformation function
(defn transform-map [m fm]
  (into {} (map (fn [[k v]]
                  [k (apply (first v)
                            ((apply juxt (rest v)) m))])
                fm)))

(transform-map data transformations)
于 2013-03-26T04:39:48.713 に答える
0

これを構造化するもう1つの一般的な方法は、最初のマップから始めて、それを超える変換関数のコレクションを減らすことです。

「キー:aと:bの合計をキー:dに入れたいとしましょう?」

user> (def m {:a 0 :b 0 :c 0 :d 0}
#'user/m 
user> (reduce #(%2 %1) m [#(assoc % :a (inc (:a %))) 
                          #(assoc % :b (inc (:b %))) 
                          #(assoc % :d (+ (:a %) (:b %)))]) 
{:a 1, :c 0, :b 1, :d 2} 

それぞれのアクション(assoc)とターゲット(:bなど)を指定する必要があるため、これはより冗長ですが、変換を表現したり、追加の引数を指定したりすることができます。おそらくもっと重要なのは、マップの内部順序に依存せずに順序を明示的にすることです。

入力を[ターゲットアクション]ペアとして構造化して、冗長性を少し少なくすることができます。

user> (reduce (fn [result [target action]] 
                  (assoc result target (action result))) 
                 m 
                 [[:a #(inc (:a %))] 
                  [:b #(inc (:b %))] 
                  [:d #(+ (:a %) (:b %))]])
{:a 1, :c 0, :b 1, :d 2}
于 2013-03-25T23:24:57.137 に答える