2012-03-12 15 views
6

W kostkach OLAP możliwe jest bardzo szybkie wyszukiwanie dużych ilości danych zagregowanych. Główną przyczyną takiego stanu rzeczy jest to, że wstępnie agregujemy dane w operacjach, które łatwo połączyć w górę (głównie +, -, średnia, std, max, min i kilka innych).Wstępnie zagregowana struktura danych w clojure

Jak uzyskać to "anty-leniwy" zachowanie w clojure?

myślę o czymś jak

(def world-population {:africa 4e8   ;;this is an aggregation! 
         :africa/liberia 3.4e6 
         :africa/ethiopia 7.4e7 
         ...}) 

Jak zaktualizować datastructure tak i upewnij się, że rodzice podmiot jest aktualizowana też? Czy trzeba wykonać własną refendycję?

Odpowiedz

3

Można napisać rekurencyjną funkcję zbiorczego jako funkcję wyższego rzędu, coś jak:

(defn rollup 
    ([data heirarchy func] 
    (loop [top (second (first heirarchy))] 
     (if (nil? (heirarchy top)) 
     (rollup data heirarchy func top) 
     (recur (heirarchy top))))) 
    ([data heirarchy func root] 
    (let [children (reduce (fn [l [k v]] (if (= v root) (cons k l) l)) '() heirarchy) 
      data (reduce (fn [d c] (if (d c) d (rollup d heirarchy func c))) data children) 
      child-values (map data children)] 
     (assoc data root (apply func child-values))))) 

które mogą być następnie wykorzystane w konkretnej operacji zbiorczego lub hierarchii lubisz:

(def populations { :africa/liberia 3.4e6 
        :africa/ethiopia 7.4e7}) 

(def geography {:africa/liberia :africa 
       :africa/ethiopia :africa 
       :africa :world}) 

(rollup populations geography +) 
=> {:africa   7.74E7, 
    :world   7.74E7, 
    :africa/ethiopia 7.4E7, 
    :africa/liberia 3400000.0} 

Oczywiście staje się bardziej skomplikowane, jeśli masz bardzo duże zbiory danych lub wiele hierarchii itd., ale to powinno wystarczyć w wielu prostych przypadkach.

+0

To jest niesamowite! Sprytny sposób korzystania z funkcji wyższego rzędu! Geografia będzie prawdopodobnie pasować do wyprowadzenia, spróbuje więcej z tym. – claj

4

Dzięki przechowywaniu danych w atomie, można dodać zegarków - zasadniczo Callbacki gdy atom jest aktualizowana

coś takiego:

(def world-population (atom {:africa 4e8 
          :africa/liberia 3.4e6 
          ...})) 

(add-watch word-population :population-change-key 
     (fn [key ref old new] 
     (prn "population change"))) 

można zbudować jakąś logikę propagacji wydarzenie na górze, że .

+0

add-watch to sprytny sposób na zsynchronizowanie struktury! Dziękuję za to! – claj

Powiązane problemy