2012-03-12 42 views
6

Trong các khối OLAP, có thể thực hiện các thao tác tra cứu rất nhanh chóng trên một lượng lớn dữ liệu tổng hợp. Lý do chính cho điều này là một dữ liệu trước khi tổng hợp trong các hoạt động dễ dàng kết hợp trở lên (chủ yếu là +, -, trung bình, std, max, min và một số chi tiết khác).Cơ sở hạ tầng được tổng hợp trước trong clojure

Làm cách nào để có hành vi "chống lười" này trong clojure?

Tôi đang nghĩ về cái gì đó như

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

Làm thế nào để cập nhật một datastructure như thế này và chắc chắn rằng các bậc phụ huynh của một thực thể được cập nhật quá? Người ta có phải cuộn triển khai thực hiện lại của riêng mình không?

Trả lời

3

Bạn có thể viết một hàm rollup đệ quy là một hàm bậc cao, một cái gì đó như:

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

nào sau đó có thể được sử dụng với bất kỳ hoạt động rollup cụ thể hoặc phân cấp bạn thích:

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

Rõ ràng nó trở nên phức tạp hơn nếu bạn có bộ dữ liệu rất lớn hoặc nhiều phân cấp, v.v. nhưng điều này là đủ cho nhiều trường hợp đơn giản.

+0

Điều này thật tuyệt vời! Cách thông minh để sử dụng các chức năng bậc cao! Địa lý có lẽ sẽ là một trận đấu tốt để lấy được, sẽ cố gắng nhiều hơn với địa lý đó. – claj

4

Bằng cách lưu trữ dữ liệu của bạn trong một nguyên tử, bạn có thể thêm đồng hồ - về cơ bản callbacks khi nguyên tử được cập nhật

Something như thế này:

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

Bạn có thể xây dựng một số logic tuyên truyền sự kiện trên hết .

+0

add-watch là một cách thông minh để giữ cấu trúc đồng bộ! Cảm ơn bạn vì điều đó! – claj

Các vấn đề liên quan