在 Clojure 中迭代时间序列时出现问题

发布于 2024-09-08 22:41:21 字数 561 浏览 2 评论 0原文

我有以下问题: 我有一个包含超过 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 吧。这将为我提供与时间序列条目相对应的值,但对于下一个时间序列条目,我将不得不再次进行所有计算。 迭代是正确的事情,但它不起作用,因为该函数有副作用。

所以我就被困在这里了。如果有人能给我提示,那就太好了。

I have the following problem:
I have a time-series with more than 10000 entries and I want to perform some calculations with each of them. This alone wouldn't be a problem, but I need to get the last calculated value in order to get the next one. A very simple form of what I need would look like this:

Val(n) = Val(n-1) + (time-series-entry / 2) (or something like it!)

I don't have any idea how to manage this. Simply doing something like this:

(defn calc-val
  [time-series element]
  (seq (cons (generate-val-element time-series element)
             (calc-val time-series (inc element)))))

wouldn't work because can't (at least I don't know how!) get the last computed value.
Then I thought: OK, let's use Loop-Recur. This would give me the value corresponding to the time-series entry BUT for the next one I would have to do all the computations again.
Iterate would be the right thing, but it didn't work because the function has side effects.

So I'm stuck here on this one. It would be great if someone could give me a hint.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我们的影子 2024-09-15 22:41:21

如果你只关心最终结果,请使用reduce;如果您需要获取依次转换每个值的结果序列(其中每个转换取决于之前的转换),请使用reductions(可在clojure.contrib.seq-utils中找到) 1.1 中的 code> 和 1.2 中的 clojure.core 中)。

下面, transform-first-entry 对第一个条目执行您想要执行的任何操作(如果您不需要以任何方式转换它,您可以省略 的第一个参数减少 / 减少并使用entries而不是(剩余条目作为最后一个参数); code> 是一个函数,它获取前一个条目和当前条目(按此顺序)的转换结果,并为当前条目生成转换结果。

;;; 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...)

请注意

,假设您想要这样做。保留第一个条目不变,并将示例转换从问题文本应用到后续条目,您可以

(defn transform-entry [prev-transformed current]
  (+ prev-transformed
     (/ current 2)))

(reduce transform-entry series) ; ...or reductions

If you only care about the final result, use reduce; if you need to get a seq of results of transforming each value in turn (where each transformation depends on the previous ones), use reductions (found in clojure.contrib.seq-utils in 1.1 and in clojure.core in 1.2).

Below, transform-first-entry does whatever you want to do to the first entry (if you don't need to transform it in any way, you can just leave out the first argument to reduce / reductions and use entries rather than (rest entries as the final argument); transform-entry is the function which takes the result of transforming the previous entry and the current entry (in this order) and produces the transformation result for the current 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...)

Note that reductions is lazy.

Assuming you wanted to leave the first entry unchanged and apply your example transformation from the question text to the subsequent entries, you could use

(defn transform-entry [prev-transformed current]
  (+ prev-transformed
     (/ current 2)))

as the reduction function in

(reduce transform-entry series) ; ...or reductions
筱果果 2024-09-15 22:41:21

如果你只是想要一个提示;考虑使用 分区< /a>.

不仅仅是一个提示......

(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 ni seq)< /code> 将 seq 分成长度为 n(本例中为 2)且重叠 i(本例中为 1)的列表部分,并且然后我们用 for 迭代这些部分,并对这些部分执行我们想要的操作。

If you just want a hint; look into using partition.

For a little more than a hint

(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)))))

Though this hasn't been tested, it should work or be close to working :)

Explanation

(partition n i seq) separates seq into parts that lists of length n (2 in this case) with overlap i (1 in this case), and then we iterate over those with for, and do what we want with the parts.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文