我正在使用Aleph从Redis中提取数据:
(apply hash-map @(@r [:hgetall (key-medication id)]))
问题是这些数据带有键的字符串,例如:
({"name" "Tylenol", "how" "instructions"})
当我需要时:
({:name“Tylenol”,“how”instructions})
我之前通过以下方式创建了新地图:
{:name(m“name”),:how(m“how”)}
但是这对于大量密钥来说效率很低。
如果有这样的功能吗?或者我必须遍历每个?
答案 0 :(得分:78)
您还可以使用clojure.walk
库来使用函数keywordize-keys
(use 'clojure.walk)
(keywordize-keys {"name" "Tylenol", "how" "instructions"})
;=> {:name "Tylenol", :how "instructions"}
这将以递归方式遍历地图,因此它也会在嵌套地图中“关键字化”键
http://clojuredocs.org/clojure_core/clojure.walk/keywordize-keys
答案 1 :(得分:41)
有一个名为keyword的便捷函数可将字符串转换为适当的关键字:
(keyword "foo")
=> :foo
所以这只是使用此函数转换地图中所有键的情况。
我可能会使用带有解构的列表理解来执行此操作,例如:
(into {}
(for [[k v] my-map]
[(keyword k) v]))
答案 2 :(得分:5)
我同意djhworld,clojure.walk/keywordize-keys
就是你想要的。
值得窥探clojure.walk/keywordize-keys
的源代码:
(defn keywordize-keys
"Recursively transforms all map keys from strings to keywords."
[m]
(let [f (fn [[k v]] (if (string? k) [(keyword k) v] [k v]))]
(clojure.walk/postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m)))
对于java互操作,逆变换有时很方便:
(defn stringify-keys
"Recursively transforms all map keys from keywords to strings."
[m]
(let [f (fn [[k v]] (if (keyword? k) [(name k) v] [k v]))]
(clojure.walk/postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m)))
答案 3 :(得分:3)
您可以使用zipmap
:
(defn modify-keys [f m] (zipmap (map f (keys m)) (vals m)))
(modify-keys keyword {"name" "Tylenol", "how" "instructions"})
; {:how "instructions", :name "Tylenol"}
基本上,zipmap
允许通过分别指定键和值来创建地图。
答案 4 :(得分:1)
或许值得注意的是,如果传入的数据为json
并且您使用的是clojure.data.json
,则可以指定key-fn
和value-fn
来操作结果解析字符串(docs) -
;; Examples from the docs
(ns example
(:require [clojure.data.json :as json]))
(json/read-str "{\"a\":1,\"b\":2}" :key-fn keyword)
;;=> {:a 1, :b 2}
(json/read-str "{\"a\":1,\"b\":2}" :key-fn #(keyword "com.example" %))
;;=> {:com.example/a 1, :com.example/b 2}
答案 5 :(得分:0)
我是第二个@mikera的into
based answer。或者,不是最简洁,但使用assoc + dissoc / reduce的另一个选项是:
(reduce #(dissoc (assoc %1 (keyword %2) (get %1 %2)) %2) my-map (keys may-map))
答案 6 :(得分:0)
使用keyword
函数和reduce-kv
。
如果我有地图,例如
(def test-map {"key1" "val1" "key2" "val2"}
我能做
(reduce-kv
(fn [m k v]
(assoc m (keyword k) v))
{} test-map)
=> {:key1 "val1" :key2 "val2"}