2013-10-22 57 views
1

我有兩個數據庫,我試圖使用一些Clojure膠水代碼保持同步。使用投影函數設置差異

我想製作一個類似於clojure.set/difference的東西,它對函數投影的值進行操作。

下面是一些樣本數據:

(diff #{{:name "bob smith" :favourite-colour "blue"} 
     {:name "geraldine smith" :age 29}} 

     #{{:first-name "bob" :last-name "smith" :favourite-colour "blue"}} 

     :name 
     (fn [x] (str (:first-name x) " " (:last-name x)))) 

;; => {:name "geraldine smith" :age 29} 

我已經得到的最好的是:

(defn diff 
    "Return members of l who do not exist in r, based on applying function 
    fl to left and fr to right" 
    [l r fl fr] 
    (let [l-project (into #{} (map fl l)) 
     r-project (into #{} (map fr r)) 
     d (set/difference l-project r-project) 
     i (group-by fl l)] 
    (map (comp first i) d))) 

但我覺得這是一個有點笨拙,我無法想象它的表現非常好。我扔掉了我想保留的信息,然後再查找它。

我有一個去使用元數據,差集期間圍繞保持原有的價值觀,但我似乎不能把元數據的基本類型,所以沒有工作......

我我不知道爲什麼,但我頭腦裏有這麼一個小小的聲音,告訴我這種操作是單子的作用,而且我應該真正瞭解單子是什麼以及如何使用它。任何關於小聲音是否正確的指導都非常受歡迎!

回答

1
(defn diff 
    [l r fl fr] 
    (let [r-project (into #{} (map fr r))] 
    (set (remove #(contains? r-project (fl %)) l)))) 

此不再直接暴露差異化經營(現在是隱式與remove/contains組合),但它是簡潔,應該給你正在尋找的結果。

例如使用和輸出:

user> (diff #{{:name "bob smith" :favourite-colour "blue"} 
       {:name "geraldine smith" :age 29}} 

      #{{:first-name "bob" :last-name "smith" :favourite-colour "blue"}} 

      :name 
      (fn [x] (str (:first-name x) " " (:last-name x)))) 

#{{:age 29, :name "geraldine smith"}} 
+0

我沒有在這裏使用一個一元的方式,並有興趣,看看如何將工作,但在一定程度上,我不明白爲什麼一個簡單的過濾操作必須被迫使用set語義。 – noisesmith

+0

你完全正確。我喜歡套!我花了太多時間編寫SQL :) –