Todavía estoy trabajando en descifrar lo de F # - tratando de encontrar la manera de 'pensar' en F # en lugar de solo traducir desde otros idiomas que conozco.Calculando una media móvil en F #
Recientemente he estado pensando en los casos en los que no tienes un mapa 1: 1 entre antes y después. Casos donde List.map se cae.
Un ejemplo de esto son los promedios móviles, donde normalmente obtendrá resultados len-n + 1 para una lista de longitudes de longitud al promediar más de n elementos.
Para los gurús que hay, ¿esta es una buena manera de hacerlo (utilizando cola pellizcada de Jomo Fisher)?
//Immutable queue, with added Length member
type Fifo<'a> =
new()={xs=[];rxs=[]}
new(xs,rxs)={xs=xs;rxs=rxs}
val xs: 'a list;
val rxs: 'a list;
static member Empty() = new Fifo<'a>()
member q.IsEmpty = (q.xs = []) && (q.rxs = [])
member q.Enqueue(x) = Fifo(q.xs,x::q.rxs)
member q.Length() = (List.length q.xs) + (List.length q.rxs)
member q.Take() =
if q.IsEmpty then failwith "fifo.Take: empty queue"
else match q.xs with
| [] -> (Fifo(List.rev q.rxs,[])).Take()
| y::ys -> (Fifo(ys, q.rxs)),y
//List module, add function to split one list into two parts (not safe if n > lst length)
module List =
let splitat n lst =
let rec loop acc n lst =
if List.length acc = n then
(List.rev acc, lst)
else
loop (List.hd lst :: acc) n (List.tl lst)
loop [] n lst
//Return list with moving average accross len elements of lst
let MovingAverage (len:int) (lst:float list) =
//ugly mean - including this in Fifo kills genericity
let qMean (q:Fifo<float>) = ((List.sum q.xs) + (List.sum q.rxs))/(float (q.Length()))
//get first part of list to initialise queue
let (init, rest) = List.splitat len lst
//initialise queue with first n items
let q = new Fifo<float>([], init)
//loop through input list, use fifo to push/pull values as they come
let rec loop (acc:float list) ls (q:Fifo<float>) =
match ls with
| [] -> List.rev acc
| h::t ->
let nq = q.Enqueue(h) //enqueue new value
let (nq, _) = nq.Take() //drop old value
loop ((qMean nq)::acc) t nq //tail recursion
loop [qMean q] rest q
//Example usage
MovingAverage 3 [1.;1.;1.;1.;1.;2.;2.;2.;2.;2.]
(Tal vez una mejor manera sería implementar un MovingAverageQueue heredando de Fifo?)
excelente, este es el tipo de respuesta que me ayuda a 'crecer' - es decir, el descubrimiento de cosas que ya existe en lugar de reinventar la rueda! – Benjol
vínculo inactivo, creo que todos los documentos se movieron a msdn por ahora, por lo que una página similar sería http://msdn.microsoft.com/en-us/library/dd233209(VS.100).aspx o http: // msdn .microsoft.com/es-us/library/ee353635 (VS.100) .aspx –
Tuve que declararlo como 'dejar MovingAverage n (s: seq) =' para poner esto en un módulo de utilidad, lejos de el sitio de llamada, para aplacar el sistema de tipos. Por lo que puedo decir, este * solo * funciona con flotadores, debido a una limitación de 'Array.average'. MSDN afirma que puedo reemplazar eso con 'Array.averageBy' para usar esto en una secuencia int, pero eso da un error diferente. Brian, ¿puedes reformular esta respuesta para que funcione en contextos genéricos, de modo que funcione con seq-de-cualquier-tipo aritmético, sin inferencia de tipo? –