동일한 키를 사용하지만 값에 함수가 적용된 하나의 값 맵을 다른 맵으로 변환하고 싶습니다. clojure api 에서이 작업을 수행하는 기능이 있다고 생각하지만 찾을 수 없었습니다.
여기 내가 찾고있는 것을 구현 한 예가 있습니다.
(defn map-function-on-map-vals [m f]
(reduce (fn [altered-map [k v]] (assoc altered-map k (f v))) {} m))
(println (map-function-on-map-vals {:a "test" :b "testing"} #(.toUpperCase %)))
{:b TESTING, :a TEST}
map-function-on-map-vals
이미 존재 하는지 아는 사람 이 있습니까? 나는 그것이 아마 더 좋은 이름을 가지고 있다고 생각할 것입니다.
답변
나는 당신의 reduce
버전을 좋아합니다 . 관용적이라고 생각합니다. 어쨌든 목록 이해를 사용하는 버전이 있습니다.
(defn foo [m f]
(into {} (for [[k v] m] [k (f v)])))
답변
당신은 사용할 수 있습니다 clojure.algo.generic.functor/fmap
:
user=> (use '[clojure.algo.generic.functor :only (fmap)])
nil
user=> (fmap inc {:a 1 :b 3 :c 5})
{:a 2, :b 4, :c 6}
답변
다음은 맵을 변환하는 상당히 일반적인 방법입니다.
zipmap
키 목록과 값 목록을 가져와 새로운 Clojure 맵을 생성하는 “올바른 일”을 수행합니다. map
키 주위를 두어 변경하거나 둘 다 할 수도 있습니다.
(zipmap (keys data) (map #(do-stuff %) (vals data)))
또는 함수로 마무리하십시오.
(defn map-function-on-map-vals [m f]
(zipmap (keys m) (map f (vals m))))
답변
Clojure 요리 책에서 가져온 reduce-kv는 다음과 같습니다.
(defn map-kv [m f]
(reduce-kv #(assoc %1 %2 (f %3)) {} m))
답변
이 작업을 수행하는 관용적 인 방법은 다음과 같습니다.
(defn map-function-on-map-vals [m f]
(apply merge
(map (fn [[k v]] {k (f v)})
m)))
예:
user> (map-function-on-map-vals {1 1, 2 2, 3 3} inc))
{3 4, 2 3, 1 2}
답변
map-map
, map-map-keys
및map-map-values
Clojure에는 기존 기능이 없다는 것을 알고 있지만 map-map-values
자유롭게 복사 할 수있는 기능을 구현했습니다 . 이 두 밀접하게 관련 기능을 함께 제공 map-map
하고 map-map-keys
또한 표준 라이브러리에서 누락 :
(defn map-map
"Returns a new map with each key-value pair in `m` transformed by `f`. `f` takes the arguments `[key value]` and should return a value castable to a map entry, such as `{transformed-key transformed-value}`."
[f m]
(into (empty m) (map #(apply f %) m)) )
(defn map-map-keys [f m]
(map-map (fn [key value] {(f key) value}) m) )
(defn map-map-values [f m]
(map-map (fn [key value] {key (f value)}) m) )
용법
다음 map-map-values
과 같이 전화 할 수 있습니다 .
(map-map-values str {:a 1 :b 2})
;; => {:a "1", :b "2"}
그리고 다른 두 가지 기능은 다음과 같습니다.
(map-map-keys str {:a 1 :b 2})
;; => {":a" 1, ":b" 2}
(map-map (fn [k v] {v k}) {:a 1 :b 2})
;; => {1 :a, 2 :b}
대체 구현
보다 일반적인 기능 없이 map-map-keys
또는 만 원하는 경우 다음과 같은 구현을 사용할 수 있습니다 .map-map-values
map-map
map-map
(defn map-map-keys [f m]
(into (empty m)
(for [[key value] m]
{(f key) value} )))
(defn map-map-values [f m]
(into (empty m)
(for [[key value] m]
{key (f value)} )))
또한 이 문구를 선호하는 경우 대신 대체 map-map
기반으로 구현 합니다.clojure.walk/walk
into
(defn map-map [f m]
(clojure.walk/walk #(apply f %) identity m) )
Parellel 버전 – pmap-map
등
필요한 경우 이러한 기능의 병렬 버전도 있습니다. 그들은 pmap
대신에 사용 합니다 map
.
(defn pmap-map [f m]
(into (empty m) (pmap #(apply f %) m)) )
(defn pmap-map-keys [f m]
(pmap-map (fn [key value] {(f key) value}) m) )
(defn pmap-map-values [f m]
(pmap-map (fn [key value] {key (f value)}) m) )
답변
저는 Clojure n00b이므로 훨씬 더 우아한 솔루션이있을 수 있습니다. 내 꺼야 :
(def example {:a 1 :b 2 :c 3 :d 4})
(def func #(* % %))
(prn example)
(defn remap [m f]
(apply hash-map (mapcat #(list % (f (% m))) (keys m))))
(prn (remap example func))
anon func은 각 키와 f’ed 값에서 약간 2 개의 목록을 만듭니다. Mapcat은 맵의 키 시퀀스에서이 기능을 실행하고 전체 작업을 하나의 큰 목록으로 연결합니다. “apply hash-map”은 해당 시퀀스에서 새 맵을 만듭니다. (% m)는 조금 이상하게 보일 수 있습니다. 연관된 값을 찾기 위해 키를 맵에 적용하는 관용적 Clojure입니다.
가장 권장되는 독서 자료 : Clojure 치트 시트 .