我有这样的哈希映射:
{:key1 "aaa bbb ccc" :key2 "ddd eee" :key3 "fff ggg" :do-not-split "abcdefg hijk"}
我想分割一些字符串来获取向量:
; expected result
{:key1 ["aaa" "bbb" "ccc"] :key2 ["ddd" "eee"] :key3 ["fff" "ggg"] :do-not-split "abcdefg hijk"}
我现在使用update-in
三次,如下所示,但看起来很难看。
(-> my-hash (update-in [:key1] #(split % #"\s"))
(update-in [:key2] #(split % #"\s"))
(update-in [:key3] #(split % #"\s")))
我希望有点像(update-all my-hash [:key1 :key2 :key3] fn)
答案 0 :(得分:4)
您可以使用reduce
:
user=> (def my-hash {:key1 "aaa bbb ccc" :key2 "ddd eee" :key3 "fff ggg"})
#'user/my-hash
user=> (defn split-it [s] (clojure.string/split s #"\s"))
#'user/split-it
user=> (reduce #(update-in %1 [%2] split-it) my-hash [:key1 :key2 :key3])
{:key3 ["fff" "ggg"], :key2 ["ddd" "eee"], :key1 ["aaa" "bbb" "ccc"]}
答案 1 :(得分:2)
只需根据决定是否分割的函数映射值。
user=> (def x {:key1 "aaa bbb ccc"
:key2 "ddd eee"
:key3 "fff ggg"
:do-not-split "abcdefg hijk"})
#'user/x
user=> (defn split-some [predicate [key value]]
(if (predicate key)
[key (str/split value #" ")]
[key value]))
#'user/split-some
user=> (into {} (map #(split-some #{:key1 :key2 :key3} %) x))
{:do-not-split "abcdefg hijk", :key3 ["fff" "ggg"], :key2 ["ddd" "eee"], :key1 ["aaa" "bbb" "ccc"]}
答案 2 :(得分:0)
这是解决问题的另一种方式。
想一想:如果你的字符串在列表中,你会如何处理它?</ p>
答案是您可以使用map
来获取向量列表:
(map #(split % #"\s") list-of-strings)
如果你认为更难以得出结论,你真正想要的是映射一个函数而不是地图的值。显然map
在这里不起作用,因为它仅适用于序列。
但是,是否有通用版本的地图?事实证明有!它被称为fmap
,来自仿函数的概念,您现在可以忽略它。这就是你如何使用它:
(fmap my-hash #(split % #"\s"))
现在看看意图如何更清晰了?
唯一的缺点是fmap不是核心功能,但它可以通过algo.generic库获得。
当然,如果在这个阶段包含一个新库感觉太多,你总是可以在this link中从库本身中获取源代码 - 并赋予其作者属性:
(into (empty my-hash) (for [[k v] my-hash] [k (your-function-here v)]))