2011-01-31 12 views
5

Estoy aprendiendo Clojure, y necesito un empujón en la dirección correcta con este problema que se me ocurrió.Pregunta idiomática sobre la transformación de la secuencia

Tengo una secuencia de eventos. Cada evento incluye una 'fecha'.

(def events 
    [ 
    [1509 :marry "Catherine of Aragon"] 
    [1527 :unmarry "Catherine of Aragon"] 
    [1533 :marry "Anne Boleyn"] 
    [1536 :unmarry "Anne Boleyn"] 
    [1536 :marry "Jane Seymour"] 
    [1537 :unmarry "Jane Seymour"] 
    [1540 :marry "Anne of Cleves"] 
    [1540 :unmarry "Anne of Cleves"] 
    [1540 :marry "Catherine Howard"] 
    [1542 :unmarry "Catherine Howard"] 
    [1543 :marry "Catherine Parr"]]) 

Quiero convertir esto en una línea de tiempo vagabunda, es decir, una secuencia que contiene un vector por año. Comenzando con el año del primer evento y continuando hasta el infinito.

[[[:marry "Catherine of Aragon"]] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [[:unmarry "Catherine of Aragon"]] [] [] [] [] [] [[:marry "Ane Boleyn"]] [] [] [[:unmarry "Anne Boleyn"] [:marry "Jayne Seymour"]] ...] 
+0

me gustaría considerar re-formateo de adherirse a la convención cecear/clojure de poner el arrastre parens en una línea, ver: http://techbehindtech.com/2010/12/09/clojure-good-coding-guidelines/ – 0x89

Respuesta

8
(def timeline 
    (let [events-by-year (group-by first events)] 
    (map #(map next (events-by-year %)) 
     (iterate inc (reduce min (keys events-by-year)))))) 

prueba rápida:

=> (take 30 timeline) 
(((:marry "Catherine of Aragon"))()()()()()()()()()()()()()()()() 
() ((:unmarry "Catherine of Aragon"))()()()()() ((:marry "Anne Boleyn"))() 
() ((:unmarry "Anne Boleyn") (:marry "Jane Seymour")) ((:unmarry "Jane Seymour")) 
()) 
3

Yo sugeriría algo así como:

(defn timeline 
    ([] (timeline (ffirst *events*) *events*)) 
    ([time evts] 
    (let [[now later] (split-with #(= time (first %)) evts)] 
     (cons (map rest now) 
      (lazy-seq (timeline (inc time) later)))))) 

prueba:

user> (take 30 (timeline)) 
(((:marry "Catherine of Aragon"))()()()()()()()()()()()()()()()()() 
((:unmarry "Catherine of Aragon"))()()()()() ((:marry "Anne Boleyn"))()() 
((:unmarry "Anne Boleyn") (:marry "Jane Seymour")) ((:unmarry "Jane Seymour"))()) 

estoy suponiendo que la lista de eventos es infinito, así :)

Actualizado con mejoras, y tomando prestadas algunas ideas de cgrand (gracias :)

+0

Gracias. Se rompe cuando hay más de un evento en la misma fecha, es decir [1515: c] [1515: d]. Sin embargo, hay muchos buenos consejos, así que tal vez pueda descifrar el resto por mi cuenta. – GHZ

+0

@GHZ Ah, lo perdí. Bueno, cgrand's fue más agradable de todos modos :) Refactorizado, dejando como una segunda opción. –

Cuestiones relacionadas