2010-07-13 16 views
8

Tengo el siguiente problema: Tengo una serie de tiempo con más de 10000 entradas y deseo realizar algunos cálculos con cada una de ellas. Esto solo no sería un problema, pero necesito obtener el último valor calculado para obtener el siguiente. Una forma muy simple de lo que necesito se vería así:Problema al iterar sobre una serie de tiempo en clojure

Val(n) = Val(n-1) + (time-series-entry/2) (! O algo parecido)

no tengo ni idea de cómo manejar esto. Basta con hacer algo como esto:

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

no funcionaría porque no puedo (al menos yo no sé cómo!) Obtener el último valor calculado. Entonces pensé: OK, usemos Loop-Recur. Esto me daría el valor correspondiente a la entrada de la serie de tiempo PERO para la siguiente tendría que hacer todos los cálculos otra vez. Iterar sería lo correcto, pero no funcionó porque la función tiene efectos secundarios.

Así que estoy atrapado aquí en este caso. Sería genial si alguien pudiera darme una pista.

Respuesta

3

Si solo quieres una pista; mira en usar partition.

Por un poco más de un toque ...

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

Aunque esto no ha sido probado, se debe trabajar o estar cerca de trabajo :)

Explicación

(partition n i seq) separa seq en partes que enumeran la longitud n (2 en este caso) con superposición i (1 en este caso), y luego iteramos sobre aquellos con for, y hacemos lo que queremos con las partes.

+0

Si yo Comprenda la pregunta correctamente, el resultado de la transformación en cada paso depende del resultado de la transformación en el paso anterior, no en la entrada anterior no transformada. Por lo tanto, indirectamente depende del fragmento inicial completo de la serie que lo precede. (Esperando ser corregido por el OP si estoy equivocado. :-)) –

+0

Si ese es el caso, absolutamente. Lo entendí de manera diferente (como su ejemplo imperativo lo hizo parecer de otra manera) ¡pero estoy feliz de estar equivocado o bien! De cualquier manera, él está en buenas manos;) – Isaac

+0

Me parece a mí también. Aquí está la esperanza de que él/ella esté de acuerdo. :-) –

7

Si solo le importa el resultado final, use reduce; si necesita obtener una secuencia de resultados de transformación de cada valor por turno (donde cada transformación depende de los anteriores), use reductions (se encuentra en clojure.contrib.seq-utils en 1.1 y en clojure.core en 1.2).

A continuación, transform-first-entry hace lo que quiere hacer a la primera entrada (si no es necesario transformarla en modo alguno, puede simplemente dejar de lado el primer argumento de reduce/reductions y utilizar entries en lugar de como (rest entries el argumento final); transform-entry es la función que toma el resultado de transformar la entrada anterior y la entrada actual (en este orden) y produce el resultado de la transformación para la entrada actual.

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

Tenga en cuenta que reductions es flojo.

Suponiendo que quería dejar la primera entrada sin cambios y aplicar su transformación ejemplo del texto de la pregunta a las entradas posteriores, se puede usar

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

como la función de reducción de

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