2013-01-31 96 views
1

我將從我的測試開始,使用speclj框架。Clojure:將字符串轉換爲散列圖中的鍵值對

(it "turns the string into a hash-map" 
    (should= {1 "1" 2 "2" 3 "3"} 
    (format-string "1=1 2=2 3=3"))) 

然後我的代碼:

(:use [clojure.string :only (split)]) 

(defn format-string [string] 
    (split string #"\s+")) 

眼下,format-string函數返回["1=1" "2=2" "3=3"]和測試失敗。正如你在我的測試中看到的那樣,我希望它返回帶有=符號的鍵值對的散列圖。

我已經嘗試了一些東西,並且已經接近,但不太明白如何進行這種轉換。

編輯

想通了一個解決方案,雖然該鍵是字符串而不是整數。

我的代碼:

(defn format-board [route] 
    (let [[first second third] (split route #"\s+")] 
    (merge 
     (apply hash-map (split-at-equals first)) 
     (apply hash-map (split-at-equals second)) 
     (apply hash-map (split-at-equals third)) 

這將返回{"1" "1" "2" "2" "3" "3"}

回答

2

您已在空格處分割,但您需要再次在=分隔符處分割。您可以使用正則表達式來進行解析。一旦你有你的配對,你可以assoc成哈希映射。在這裏,我用reduce來實現轉換。

user=> (reduce #(assoc % (read-string (nth %2 1)) (nth %2 2)) {} 
    #_> (re-seq #"([^=\s]+)=([^=\s]+)" "1=1 2=2 3=3")) 
{3 "3", 2 "2", 1 "1"} 

注意鍵順序是不適用使用clojure.core.reducers潛在並行版本散列地圖

user=> (= {1 "1", 2 "2", 3 "3"} *1) 
true 
+0

謝謝 - 我編輯我的問題,包括我寫的解決方案,但它不是那裏。你的工作,雖然我正在努力修改它更可擴展。例如,如果字符串包含更多對,例如4 = 4 5 = 5 6 = 6等,該怎麼辦? – rzv

+0

@rzv這將適用於任何數量的配對。例如,嘗試'(reduce#(assoc%(read-string(nth%2 1))(nth%2 2)){} (reqseq#「([^ = \ s] +)=([^= \ s] +)「」1 = 1 2 = 2 3 = 3 4 = 4 5 = 5:foo = 6:bar = 7「))' –

+0

啊,太棒了!你是對的,那很好。你能否偶然帶我看看發生了什麼?這有點簡潔。 – rzv

0

這裏:

(require '[clojure.core.reducers :as r]) 
(require '[clojure.string :as s]) 

(def string-of-pairs "1=1 2=2 3=3 4=4") 

; reducing fn to convert seq of (key, value) to hash-map 
(defn rf ([] {}) ([acc [k v]] (assoc acc k v))) 

; for large colls, fold will parallelize execution 
(r/fold merge rf (r/map #(s/split % #"=") (s/split string-of-pairs #"\s+"))) 

爲了更好地理解減速機,看this video其中 Rich解釋了減速器的動機並演示了一些用法。

相關問題