2017-03-12 38 views
2

我有一個原子fs,我正在更新遞歸函數freq-seq這是保存我的計算結果的值。我有另一個功能mine-freq-seqs開始freq-seq,當mine-freq-seqs完成後,我想收到所述原子的最後一個值。所以我想我會做它像這樣在遞歸函數完成後deref一個原子

(ns freq-seq-enum) 

(def fs (atom #{})) 

(defn locally-frequents 
    [sdb min-sup] 
    (let [uniq-sdb (map (comp frequencies set) sdb) 
     freqs (apply merge-with + uniq-sdb)] 
    (->> freqs 
     (filter #(<= min-sup (second %))) 
     (map #(vector (str (first %)) (second %)))))) 


(defn project-sdb 
    [sdb prefix] 
    (if (empty? prefix) sdb 
         (into [] (->> sdb 
          (filter #(re-find (re-pattern (str (last prefix))) %)) 
          (map #(subs % (inc (.indexOf % (str (last prefix)))))) 
          (remove empty?))))) 


(defn freq-seq 
    [sdb prefix prefix-support min-sup frequent-seqs] 
    (if ((complement empty?) prefix) (swap! fs conj [prefix prefix-support])) 
    (let [lf (locally-frequents sdb min-sup)] 
(if (empty? lf) nil 
       (for [[item sup] lf] (freq-seq (project-sdb sdb (str prefix item)) (str prefix item) sup min-sup @fs))))) 

(defn mine-freq-seqs 
    [sdb min-sup] 
    (freq-seq sdb "" 0 min-sup @fs)) 

運行它首先

(mine-freq-seqs ["CAABC" "ABCB" "CABC" "ABBCA"] 2) 

然後DEREF-ING原子 (deref fs)

產量

#{["B" 4] 
    ["BC" 4] 
    ["AB" 4] 
    ["CA" 3] 
    ["CAC" 2] 
    ["AC" 4] 
    ["ABC" 4] 
    ["CAB" 2] 
    ["A" 4] 
    ["CABC" 2] 
    ["ABB" 2] 
    ["CC" 2] 
    ["CB" 3] 
    ["C" 4] 
    ["BB" 2] 
    ["CBC" 2] 
    ["AA" 2]} 

然而(doall (mine-freq-seqs ["CAABC" "ABCB" "CABC" "ABBCA"] 2) (deref fs))

只是給#{}

我想要的是讓那麼freq-seq遞歸完成獲得原子fs的價值。所以我可以撥打mine-freq-seq,並在REPL中返回我的結果,而不必在此處手動刪除它。

+0

這不適合我。你能否提供'lfs'函數並添加你的原子初始化?你的功能應該做什麼?你能添加輸入/期望的輸出嗎? – jmargolisvt

+0

請參閱[這裏](https://gist.github.com/themistoklik/4203bb184617c66512b5fdbd49e4d0cc)。它應該提供一個頻繁的序列枚舉。期望的輸出已經實現。當我使用doall時,我得到#{}。當我到達我的家用機器時,我會完全編輯。 – themistoklik

+1

如果您可以使var名稱更具描述性,並且可以簡化爲最小示例,則會更容易理解您嘗試執行的操作。 –

回答

1

我改變了一下,刪除了所有的懶惰位(這在repl中默默地發生,但當它在repl之外改變時可能會引起混淆)。請注意0​​,mapvdoall的更改。至少現在我得到你的結果:

(def fs (atom #{})) 

(defn locally-frequents 
    [sdb min-sup] 
    (let [uniq-sdb (map (comp frequencies set) sdb) 
     freqs (apply merge-with + uniq-sdb)] 
    (->> freqs 
     (filter #(<= min-sup (second %))) 
     (mapv #(vector (str (first %)) (second %)))))) 


(defn project-sdb 
    [sdb prefix] 
    (if (empty? prefix) 
    sdb 
    (into [] (->> sdb 
       (filter #(re-find (re-pattern (str (last prefix))) %)) 
       (map #(subs % (inc (.indexOf % (str (last prefix)))))) 
       (remove empty?))))) 


(defn freq-seq 
    [sdb prefix prefix-support min-sup frequent-seqs] 
    (if ((complement empty?) prefix) (swap! fs conj [prefix prefix-support])) 
    (let [lf (locally-frequents sdb min-sup)] 
    (if (empty? lf) 
     nil 
     (vec (for [[item sup] lf] (freq-seq (project-sdb sdb (str prefix item)) (str prefix item) sup min-sup @fs)))))) 

(defn mine-freq-seqs 
    [sdb min-sup] 
    (freq-seq sdb "" 0 min-sup @fs)) 

(doall (mine-freq-seqs ["CAABC" "ABCB" "CABC" "ABBCA"] 2)) 

(deref fs) => #{["B" 4] ["BC" 4] ["AB" 4] ["CA" 3] 
       ["CAC" 2] ["AC" 4] ["ABC" 4] ["CAB" 2] 
       ["A" 4] ["CABC" 2] ["ABB" 2] ["CC" 2] ["CB" 3] 
       ["C" 4] ["BB" 2] ["CBC" 2] ["AA" 2]} 

我還不太確定的目標是什麼,或者如何/爲什麼你喜歡「中非商會」項目。

+0

目標是給出一個序列數據庫(sdb)來提供一個頻繁的序列枚舉,如[這裏]所述(http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.6.2704&rep=rep1&type=pdf )。 「CABC」是出現兩次的序列,一次在「CABC」中,一次作爲「CAABC」的後續序列。該算法在數據挖掘中有應用,我試圖用好奇心來實現它。用我的代碼來獲得我的結果,我不得不手動deref fs,而現在我可以自動添加(deref fs)到mine-freq-seqs和deref的末尾。你的代碼似乎工作,所以謝謝你! – themistoklik

2

首先一些替代代碼沒有原子,然後看看爲什麼你得到空回報。

一個更緊湊的版本,其中一個字符串中的序列是用reduce而不是用regex和substr遞歸派生的。

然後只是對這些結果做一個頻率。

(defn local-seqs 
    [s] 
    (->> s 
     (reduce (fn [acc a] (into acc (map #(conj % a) acc))) #{[]}) 
     (map #(apply str %)) 
     (remove empty?))) 

(defn freq-seqs 
    [sdb min-sup] 
    (->> (mapcat local-seqs sdb) 
     frequencies 
     (filter #(>= (second %) min-sup)) 
     set)) 

就是這樣! 我沒有涉及一個原子,因爲我沒有看到需要,但如果你喜歡freq-seqs,最後加上它。

對於你原來的問題:爲什麼你看到的回報?

您正在致電doall,其中包含2個參數,即您的調用結果和一個集合。 doall是一個函數而不是宏,所以deref立即執行。

(defn doall 
    ;; <snip> 
    ([n coll]  ;; you have passed #{} as coll 
    (dorun n coll) ;; and this line evals to nil 
    coll)   ;; and #{} is returned 

你已通過你的結果,作爲n ARG和一個空集作爲科爾(從(deref fs)

現在,當doall電話dorun,它可能會遇到以下:

(defn dorun 
;; <snip> 
([n coll] 
(when (and (seq coll) (pos? n)) ;; coll is #{} so the seq is falesy 
    (recur (dec n) (next coll)))) ;; and a nil is returned 

由於來自fs的空集是第二個參數(coll),而and是一個宏,它將在(seq coll)上有誤,返回零,然後doall返回它是第二個空集RG。

最後一點:

所以這是一些作品,爲什麼你的失敗。至於你如何做工作,以固定電話上面我想:

(do (doall (mine-freq-seqs ["CAABC" "ABCB" "CABC" "ABBCA"] 2)) 
    (deref fs)) 

更接近於工作,但在你的過程中recusion,它只強制EVAL深一個層次。所以你可以把doall更深入到你的funcs中,但是我已經提出了一個完全不同的內部結構,所以如果你真的需要這個結構,我會把剩下的給你。