新手克洛尔问题警报..。
我有一个Clojure向量,它看起来如下所示:
(def sample-data
[{:date "2014-01-01" :value 5}
{:date "2014-01-02" :value 7}
{:date "2014-01-03" :value 6}
{:date "2014-01-04" :value 7}
{:date "2014-01-07" :value 11}])实际上它比那个要大得多,但你有个大致的想法.-它是一个单一值的向量,每天收集一次。向量将按:日期顺序排序,但对于奇数缺失的样本,存在空白。
我想要创建一个函数,它在'sample-data‘中接受一个:date,并告诉我:那个日期的值大于前一个日期的:value。拐角处案件:
我想把这个函数称为。
(value-increased? sample-data {:date '2014-01-03'})得到一个布尔响应。在这种情况下,它将是假的,因为2014-01-03 (6)的数值比前一天的值(7)要小。
提前感谢
发布于 2014-02-04 08:06:15
(defn has-value-increased?
[sample searched-date]
(reduce (fn [_ [{:keys prev-value :value} {:keys [value date]}]]
(if (and (= date searched-date)
(< prev-value value))
(reduced true)))
nil
(partition 2 1 sample)))注意,这可能效率很低,因为每次调用函数时都可以遍历整个示例。根据实际应用程序的不同,最好编写一个函数,收集值在一次传递中增加的所有日期,然后将其作为一组返回,然后将其作为函数调用,以检查日期是否增加。
以下是修改后的函数:
(defn collect-dates-with-increased-value
[sample]
(reduce (fn [acc [{prev-value :value} {:keys [date value]}]]
(cond-> acc
(< prev-value value) (conj date)))
[]
(partition 2 1 sample)))然后收集日期,例如在REPL:
=> (def dates-with-increased-value (set (collect-dates-with-increased-value sample-data)))
=> dates-with-increased-value
#{"2014-01-02" "2014-01-04" "2014-01-07"}
=> (dates-with-increased-value "2014-01-02")
"2014-01-02"
=> (dates-with-increased-value "2014-01-03")
nil 发布于 2014-02-04 08:06:31
您可以使用二进制搜索找到给定日期的索引,然后检查该索引中的条目和前面的条目。
或者,您也可以使用mikera的时间线库,它提供了一种数据结构,用于精确地维护这种类似向量的日志、时间戳值和在这些日志上操作的各种函数:
(require '[mikera.timeline :as tl])
(def t
(-> (tl/timeline)
;; (tl/log timestamp value)
(tl/log 0 0)
(tl/log 86400000 1)))然后,tl/seek允许您在给定时间之前找到最后一个条目的索引,而在给定索引处的条目可以用nth提取。
最后,clj时间对于指定时间(并且已经是时间的依赖关系)非常有用:
(tl/log (tl/timeline) (clj-time.core/now) :foo)
;= #<Timeline [[#<Instant 2014-02-04T08:00:08.290Z> :foo]]>发布于 2014-02-04 08:21:58
如果您尝试这段代码,您可以注释(首先..)的每一行去看看哪一步能做什么。
(->>
sample-data
(filter :value)
(map #(assoc % :date (.parse (java.text.SimpleDateFormat. "yyyy-MM-dd") (:date %))))
;parse date
(sort-by :date)
(partition 2 1) ;partition the sequence into every two consecutive days that have a :date value
(map (fn [[f s]] ;destructure vector into first day f and second day s
(conj s [:in-order (< (:value f) (:value s))])))
;compare days, return second date with compare boolean in in :in-order key
(remove :in-order) ;filter where :in-order is false
first ;take first false :in-order, and stop processing
)https://stackoverflow.com/questions/21546342
复制相似问题