我有以下问题: 我有一个超过10000个条目的时间序列,我想对它们进行一些计算。仅此一点不会成为问题,但我需要获取最后一个计算值以获得下一个值。我需要的一个非常简单的形式如下:
Val(n) = Val(n-1) + (time-series-entry / 2)
(或类似的东西!)
我不知道如何管理这个。简单地做这样的事情:
(defn calc-val
[time-series element]
(seq (cons (generate-val-element time-series element)
(calc-val time-series (inc element)))))
不起作用,因为不能(至少我不知道怎么做!)得到最后一个计算值。 然后我想:好吧,让我们使用Loop-Recur。这将给出对应于下一个时间序列条目BUT的值,我将不得不再次进行所有计算。 迭代是正确的,但它不起作用,因为该函数有副作用。
所以我被困在这一个。如果有人能给我一个提示,那就太好了。
答案 0 :(得分:7)
如果您只关心最终结果,请使用reduce
;如果您需要获得一系列依次转换每个值的结果(每个转换取决于之前的转换),请使用reductions
(在clojure.contrib.seq-utils
中的1.1和clojure.core
中找到1.2)。
下面,transform-first-entry
对第一个条目执行任何操作(如果您不需要以任何方式对其进行转换,则可以省略第一个参数reduce
/ { {1}}并使用reductions
而不是entries
作为最终参数); (rest entries
是一个函数,它获取转换前一个条目和当前条目(按此顺序)的结果,并生成当前条目的转换结果。
transform-entry
请注意;;; only care about the final result
(reduce transform-entry
(transform-first-entry (first series))
(rest entries))
;;; need to get a seq of intermediate results
(reductions ...arguments as above...)
是懒惰的。
假设您想要保持第一个条目不变并将示例转换从问题文本应用到后续条目,您可以使用
reductions
作为
中的缩减功能(defn transform-entry [prev-transformed current]
(+ prev-transformed
(/ current 2)))
答案 1 :(得分:3)
如果你只是想要一个提示;考虑使用partition
。
仅仅提示 ......
(defn calc-val
[time-series element]
(let [p (partition 2 1 time-series)]
(for [t p]
(let [first-value (first t)
second-value (second t)]
(do whatever you need to here)))))
虽然这尚未经过测试,但应该可以正常工作或接近工作:)
<强>解释强>
(partition n i seq)
将seq
分成长度为n
的列表(本例中为2),重叠i
(在本例中为1),然后我们迭代那些for
的人,并按照部分做我们想做的事。