2012-02-23 14 views
32

我從Redis的使用阿萊夫拉動數據Clojure:將散列映射關鍵字字符串轉換爲關鍵字?用繩子</p> <pre><code>(apply hash-map @(@r [:hgetall (key-medication id)])) </code></pre> <p>問題是這個數據來自回來的鍵,例如::

({"name" "Tylenol", "how" "instructions"}) 

當我需要它是:

({:名爲 「泰諾」:如何「說明})

我先前通過創建新的地圖:

{:名稱(M 「名稱」),:如何(M 「如何」)}

但是,這是低效的大量鍵。

如果有這樣的功能?或者我必須循環遍歷每個?

回答

40

有一個叫keyword方便的功能是將字符串轉換成相應的關鍵詞:

(keyword "foo") 
=> :foo 

所以它只是使用此功能轉換所有鍵在地圖的情況。

我可能會使用列表理解與解構要做到這一點,是這樣的:

(into {} 
    (for [[k v] my-map] 
    [(keyword k) v])) 
+0

呀貌似基本迭代是最簡單的解決方案,是檢查是否有對地圖的標準功能。但是這不難抽象。謝謝 – dMix

+3

有一個標準函數(在覈心庫),這將做到這一點,看到我的答案 – djhworld

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

下面是鑰匙和vals保證是在同一順序? – gtrak

+0

不確定。我不知道如何檢查。 – viebel

+0

http://stackoverflow.com/questions/10772384/clojures-maps-are-keys-and-vals-in-same-order – Inshallah

73

您還可以使用clojure.walk庫函數keywordize-keys

(use 'clojure.walk) 
(keywordize-keys {"name" "Tylenol", "how" "instructions"}) 
;=> {:name "Tylenol", :how "instructions"} 

這將引導地圖,以實現所期望的結果遞歸以及因此它將在嵌套的地圖太

「keywordize」鍵http://clojuredocs.org/clojure_core/clojure.walk/keywordize-keys

+2

它似乎並不適用於嵌套地圖。 –

4

我同意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))) 
0

我第二@ mikera的into based answer。另外,不是最簡潔的,但是,另一個assoc命令使用選項+ dissoc /減少將是:

(reduce #(dissoc (assoc %1 (keyword %2) (get %1 %2)) %2) my-map (keys may-map)) 
0

也許值得指出的是,如果輸入的數據是json並且使用的是clojure.data.json,你可以同時指定key-fn和對解析字符串(docs)操縱結果的value-fn -

;; 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} 
相關問題