2012-02-23 11 views
32

Clojure:ハッシュマップのキー文字列をキーワードに変換しますか?私はアレフを使用してのRedisからデータを引っ張ってる

(apply hash-map @(@r [:hgetall (key-medication id)])) 

問題は、このデータを元のために、キーの文字列で戻ってくるです:

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

私はそれがために必要がある場合:

({:名称 "タイレノール":どの「指示})

Iは、以前介して新しいマップを作成した:

{:名前(M "名前"):方法(M "方法")}

しかし、これは大量のために非効率的ですキー。

これを行う関数がある場合は、または、それぞれをループする必要がありますか?

答えて

40

適切なキーワードに文字列を変換keywordと呼ばれる便利な機能があります:

(keyword "foo") 
=> :foo 

だから、それだけでこの機能を使用して、マップ内のすべてのキーを変換する場合です。

は、私はおそらくこれを行うために非構造でリストの内包表記を使用したい、何かのように:あなたは非常にエレガントzipmapを使用してこれを達成することができます

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

基本的な反復がマップするための標準的な機能があったかどうかをチェックして、最も簡単な解決策であるようにそうに見えます。しかし、それを抽象化するのは難しくありません。ありがとう – dMix

+3

それは、コアのlibsでそれを行う標準的な機能は、 – djhworld

3

(defn modify-keys [f m] (zipmap (map f (keys m)) (vals m))) 
(modify-keys keyword {"name" "Tylenol", "how" "instructions"}) 
; {:how "instructions", :name "Tylenol"} 

基本的には、zipmapは作成することができますキーと値を別々に指定してマップを作成します。

ます。また、それはあまりにも、ネストされたマップ内の「keywordize」キー意志

ので、これは同様に再帰的にマップを歩いていくkeywordize-keys

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

機能で所望の結果を達成するためにclojure.walkライブラリを使用することができます

+4

私の答えを参照してください同じ順序であることを保証キーと価値ですか? – gtrak

+0

わかりません。私はチェックする方法を知らない。 – viebel

+0

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

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

I二mikeraのinto based answer @。また、最も簡潔ではないけど、+ dissoc /削減連想を使用して別のオプションは、次のようになります。

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

おそらく着信データがjsonであり、あなたがclojure.data.jsonを使用している場合、あなたは両方のAを指定することができ、ことは注目に値します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} 
関連する問題