我是Clojure和函数编程的新手,现在我遇到了问题。我得到了这样一个数据结构:
{
:service1 \a
:service2 \b
:service3 \c
:default \d
:alert-a {
:duration "00:00-23:59"
:if-alert true
:continuous-times 2
:time-interval [2 6 9 15 30 60]
:times -1
}
:alert-b {
:duration "09:00-23:00"
:if-alert true
:continuous-times 2
:time-interval [2 6 9 15 30 60]
:times -1
}
:alert-c {
:duration "00:00-23:59"
:if-alert true
:continuous-times 5
:time-interval [5]
:times 1
}
:alert-d {
:duration "00:00-23:59"
:if-alert true
:continuous-times 5
:time-interval [5 15 30 60]
:times -1
}
}
这是从配置文件中读取的内容。我想使用:duration
将所有clj-time
值更改为DateTime对象。所以我可以得到类似的东西:
{
:service1 \a
:service2 \b
:service3 \c
:default \d
:alert-a {
:duration DateTime Object
:if-alert true
:continuous-times 2
:time-interval [2 6 9 15 30 60]
:times -1
}
:alert-b {
:duration DateTime Object
:if-alert true
:continuous-times 2
:time-interval [2 6 9 15 30 60]
:times -1
}
:alert-c {
:duration DateTime Object
:if-alert true
:continuous-times 5
:time-interval [5]
:times 1
}
:alert-d {
:duration DateTime Object
:if-alert true
:continuous-times 5
:time-interval [5 15 30 60]
:times -1
}
}
但数据结构是不可变的。这是其他语言中的一个简单问题,但现在我不知道在一整个下午之后该怎么做。
那么有人能给我一些建议吗?我使用的数据结构不好吗?或者这个问题可以通过某种方式以某种方式解决。
答案 0 :(得分:4)
虽然您正在使用不可变数据结构,但您可以轻松高效地返回基于原始数据的新数据结构。
在这种情况下,最简单(如果重复)的解决方案是:
(-> m
(update-in [:alert-a :duration] parse-duration)
(update-in [:alert-b :duration] parse-duration)
(update-in [:alert-c :duration] parse-duration)
(update-in [:alert-d :duration] parse-duration))
这里要认识到的重要一点是update-in
不会改变它正在处理的数据结构。相反,它返回一个应用了修改的新数据结构。
线程宏->
允许新的数据结构穿过update-in
操作,以便最终返回的值是应用了所有更新的原始数据结构。
解析持续时间函数可能看起来像这样:
(defn parse-duration
"Convert duration in HH:MM-HH:MM format"
[s]
(let [[t1 t2] (clojure.string/split s #"-"))
(Period. (clj-time.coerce/to-date-time t1)
(clj-time.coerce/to-date-time t2)))
答案 1 :(得分:1)
在函数式编程中,您不需要修改集合,而是创建具有由新值替换的所需值的新集合。幸运的是,Clojure为此提供了许多有用的功能。对于您的情况update-in
应该运作良好。它采用集合(例如map),嵌套键序列和应用于键序列定义的最嵌套值的函数。例如:
> (def m {:a 1 :b 2 :c {:c1 1 :c2 2}})
#'sandbox5448/m
> m
{:a 1, :c {:c1 1, :c2 2}, :b 2}
> (update-in m [:c :c1] str)
{:a 1, :c {:c1 "1", :c2 2}, :b 2}
请注意密钥序列1
的值[:c :c1]
如何转换为"1"
。
因此,将:duration
的{{1}}字段转换为:alert-a
就像写作一样简单:
DateTime
其中> (update-in your-map [:alert-a :duration] string-to-date)
是转换器功能。