2014-10-01 33 views
0

我有一個遞歸函數,每次調用時都會出現一個散列。在Clojure的遞歸函數中維護狀態

它繞一圈哈希第一次是:

{1 "mary", 2 "dean"} 

下一輪吐出

{23 "ava", 4 "scout"} 

,並在最後一輪的回報

{3 "bina", 16 "bob"} 

我的功能將始終返回上一輪數據{3「gina」,16「bob」}。 我想,而不是吐出最後一塊數據,將它們全部存儲在一個巨大的散列中,以便我可以比較它們。在比較它們之後,函數應該返回「ava」,因爲那是與最高密鑰關聯的值。什麼是最好的方式去做這件事?

+3

你嘗試了什麼?請給我們一些代碼。 – 2014-10-01 22:12:58

回答

1

一種常規模式是爲遞歸函數添加一個狀態參數,並提供添加初始狀態值的函數的參數。然後在基本情況下,您可以對狀態值進行後處理。

這裏是建立在第一奇數前地圖的輸入的隨機值的一個例子:

user> (defn example 
     ([input] (example input {})) ;; one argument recurs with default value 
     ([input state]    ;; two arg case passes the state. 
      (if (odd? (first input)) 
      state 
      (recur (rest input) 
        (assoc state (first input) (rand-int 10)))))) 
#'user/example 

,另一種選擇最高值形成所得狀態:

user> (example [2 4 8 9]) 
{8 0, 4 1, 2 4} 
user> (defn example 
     ([input] (example input {})) 
     ([input state] 
      (if (odd? (first input)) 
      (first (sort-by val state)) 
      (recur (rest input) 
        (assoc state (first input) (rand-int 10)))))) 
#'user/example 
user> (example [2 4 8 9]) 
[8 6] 
1

如果你有一個邊界有效的函數來分析一系列值,那麼將它建模爲一個序列。如果序列終止,大概該函數會返回一個無效值。

功能

(defn ensequence [f! valid?] 
    (take-while valid? (repeatedly f!))) 

...返回由側有效功能f!產生的值的序列,終止每當valid?測試失敗。

例如,

(ensequence #(rand-int 10) #(not= 5 %)) 

...返回隨機值序列中(range 10),第一5前剛剛停止:

(6 9) 

...例如(您milage 各不相同)。

要顯示ensequence作品在您的情況如何,我們使用的反函數,輪流順序進入返回其連續元素的函數,nil後:

(defn oracle! [coll] 
    (let [s (atom coll)] 
    (fn [] (let [x (first @s)] (swap! s rest) x)))) 

例如,

(repeatedly 10 (oracle! (range 5))) 
;(0 1 2 3 4 nil nil nil nil nil) 

爲您的數據

(def data [{1 "mary", 2 "dean"} {23 "ava", 4 "scout"} {3 "bina", 16 "bob"}]) 

功能

(oracle! data) 

...先後返回其元素,其次是nil S:

(repeatedly 10 (oracle! data)) 
;({1 "mary", 2 "dean"} {23 "ava", 4 "scout"} {3 "bina", 16 "bob"} 
    nil nil nil nil nil nil nil) 

我們可以利用這個ensequence,但它產生,恢復原來的順序:

(ensequence (oracle! data) identity) 
;({1 "mary", 2 "dean"} {23 "ava", 4 "scout"} {3 "bina", 16 "bob"}) 

由於nil是虛假的,在這裏永遠不會有效,所以identity是一個很好的有效性測試。

現在我們已經有了序列,我們可以隨心所欲地做任何事情。在你的情況下,我們只是

  • 將地圖連接成一個大的map-entries序列;
  • 找到最多條目key;和
  • 取其val

這樣:

(val (apply max-key key (reduce concat data))) 
;"ava" 

我們應該用代替相當於data,但它並沒有任何區別。