2017-01-03 61 views
0

我已經寫了一個函數,它使用遞歸來查找列表中的元素數量,並且它可以成功運行,但是,我並不特別喜歡我的方式寫它。現在我已經寫了一種方法,我似乎無法想到另一種方式。Clojure - 使用遞歸來查找列表中的元素數量

我的代碼如下:

(def length 
(fn [n] 
    (loop [i n total 0] 
    (cond (= 0 i) total 
    :t (recur (rest i)(inc total)))))) 

對我來說好像是過於複雜,任何人都可以想到的另一種方式這可以用於比較寫?

任何幫助非常感謝。

+0

爲什麼不直接使用https://clojuredocs.org/clojure.core/count? – jmargolisvt

+0

我必須使用遞歸工作,這就是爲什麼我已經走下了使用循環的路線,以及爲什麼它最終變得如此複雜。遞歸使用count會有意義嗎? – benjano

+1

使用'loop-recur'你只需要一個循環,而不是遞歸。 –

回答

2

這裏是一個天真的遞歸版本:

(defn my-count [coll] 
    (if (empty? coll) 
     0 
     (inc (my-count (rest coll))))) 

請記住還有的不會是任何尾調用優化會在這裏這麼長時間列出了堆棧溢出。

下面是使用reduce版本:

(defn my-count [coll] 
    (reduce (fn [acc x] (inc acc)) 0 coll)) 
2

這是顯示一些不同解決方案的代碼。通常情況下,您應該使用內置功能count

(def data [:one :two :three]) 

(defn count-loop [data] 
    (loop [cnt 0 
     remaining data] 
    (if (empty? remaining) 
     cnt 
     (recur (inc cnt) (rest remaining))))) 

(defn count-recursive [remaining] 
    (if (empty? remaining) 
     0 
     (inc (count-recursive (rest remaining))))) 

(defn count-imperative [data] 
    (let [cnt (atom 0)] 
    (doseq [elem data] 
     (swap! cnt inc)) 
    @cnt)) 

(deftest t-count 
    (is (= 3 (count data))) 
    (is (= 3 (count-loop data))) 
    (is (= 3 (count-recursive data))) 
    (is (= 3 (count-imperative data)))) 
+1

爲什麼還要提到如何用原子做到這一點?這是任何人都會反對的反對模式;如果你想爲另外兩種好的方法增加第三種方法,減少將是展示的功能。 – amalloy

+0

有時候一個命令式/可變式的方法是最簡單的答案(顯然,這個例子中的所有東西都是「矯枉過正」)。如果任何人都看不到的代碼是必要的或可變的,並且它不泄漏,爲什麼要擔心呢?如果你深入挖掘,一切都是可變的/必要的。只有在泄漏出來時纔會成爲問題。 –

+0

這是一種非常強調圖靈機的思維方式。或者你可以說,如果你深入挖掘(lambda微積分),一切都是遞歸的。只有當你必須在現實生活中的現代物理處理器上實現它時,纔會泄漏必要的實現細節。 – amalloy

0

只是爲了完整性,這裏是另一個扭曲

(defn my-count 
    ([data] 
    (my-count data 0)) 
    ([data counter] 
    (if (empty? data) 
    counter 
    (recur (rest data) (inc counter))))) 
1

這裏有一個是尾部調用優化,並且不依賴於loop。基本上和Alan Thompson的第一個一樣,但內在功能是最好的。 (對我來說,感覺更習慣用法。):-)

(defn my-count [sq] 
(letfn [(inner-count [c s] 
      (if (empty? s) 
      c 
      (recur (inc c) (rest s))))] 
    (inner-count 0 sq))) 
相關問題