【问题标题】:Clojure: Transform string into key-value pairs in hash-mapClojure:将字符串转换为哈希映射中的键值对
【发布时间】:2013-01-31 20:36:36
【问题描述】:

我将从使用speclj 框架的测试开始。

(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"}

【问题讨论】:

    标签: string clojure hashmap


    【解决方案1】:

    您已在空格处拆分,但您需要在 = 分隔符处再次拆分。您可以使用正则表达式进行解析。一旦你有了你的配对,你可以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"}
    

    注意键顺序不适用于哈希映射

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

    【讨论】:

    • 谢谢 - 我编辑了我的问题以包含我写的解决方案,但它并不完全在那里。你的工作,虽然我正在努力修改它以使其更具可扩展性。例如,如果字符串包含更多对,如 4=4 5=5 6=6 等?
    • @rzv 这适用于任意数量的对。例如,尝试(reduce #(assoc % (read-string (nth %2 1)) (nth %2 2)) {} (re-seq #"([^=\s]+)=([^=\s]+)" "1=1 2=2 3=3 4=4 5=5 :foo=6 :bar=7"))
    • 啊,太好了!你是对的,这很好用。你能不能顺便带我看看那里发生了什么?有点简洁。
    • @rsv 我可以稍后解释,但您可以在 REPL 中探索。只需从最里面的形式开始,看看它做了什么,进行实验,然后向外移动。我怀疑您缺少reduce 的强大功能,它应该是您的首选工具之一。见learningclojure.com/2010/08/reduce-not-scary.html
    • re-seq 的用法很好,我喜欢。
    【解决方案2】:

    这是使用clojure.core.reducers 的潜在并行版本:

    (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 where Rich 解释了 reducer 背后的动机并演示了一些用法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      • 2013-11-20
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      相关资源
      最近更新 更多