2014-10-07 41 views
4

我想拿一個數字,20,和一個列表。 '(1 2 3 4 5 6 7 8 9 10),並返回包含原始列表中每個值的兩個值的集合:原始值與將該值潛入20時的餘數成對。如果原始值以某種方式鍵入餘數,這將很好,這樣我就可以輕鬆地檢索出產生特定餘數的每個數字。基本上我想要一些功能funcClojure:在列表中進行復雜迭代?

user=> (func 20 '(1 2 3 4 5 6 7 8 9 10)) 
'(:0 1, :0 2, :2 3,... :20 0) 

不過,我有一個非常困難的時期剛剛搞清楚如何遍歷列表。有人可以幫助我理解如何獨立使用列表元素,然後如何返回20除以的元素,並返回餘數?

我的想法是在計算平方根的程序中使用類似的東西。如果數字是由剩餘鍵,然後我可以查詢集合來獲取與0


這裏是我的打算有關初步的方式其餘將輸入所有數字。

;; My idea on the best way to find a square root is simple. 
;; If I want to find the square root of n, divide n in half 
;; Then divide our initial number (n) by all numbers in the range 0...n/2 
;; Separate out a list of results that only only return a remainder of 0. 
;; Then test the results in a comparison to see if the elements of our returned 
;; list when squared are equal with the number we want to find a square root of. 
;; First I'll develop a function that works with evens and then odds 

(defn sqroot-range-high-end [input] (/ input 2)) 
(sqroot-range-high-end 36) ; 18 

(defn make-sqrt-range [input] (range (sqroot-range-high-end (+ 1 input)))) 
(make-sqrt-range 36) ; '(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18) 

(defn zero-culler [input] (lazy-seq (remove zero? (make-sqrt-range input)))) 
(zero-culler 100) ; '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18) 

(defn odd-culler [input] (lazy-seq (remove odd? (zero-culler input)))) 
(odd-culler 100) ; '(2 4 6 8 10 12 14 16 18) 

;;the following is where I got stuck 
;;I'm new to clojure and programming, 
;;and am just trying to learn in a way that I understand 

(defn remainder-culler [input] 
    (if 
    (/ input (first odd-culler (input))) 
    input) 
    (recur (lazy-seq (input))) 
) 

(remainder-culler 100) 
+2

你不需要在lazy-seq中換行,它已經很懶。 – 2014-10-07 18:07:00

回答

5

歡迎的Clojure !

快速注意:[1 2 3 4 5 6 7 8 9 10]是一個向量,而不是一個列表。

當你說「鍵入到」,然後讓我覺得你正在尋找的東西,它返回一個地圖。

地圖

這是Clojure's cheatsheet進來非常方便。你正試圖從一個函數創建一個映射。地圖是一種集合,所以如果您轉到備忘單上的「集合」部分,並向下滾動到地圖,您將看到許多類別。你想創建一個,所以看看這個列表,並探索鏈接到Clojure的文檔。

這將導致你到非常方便group-by功能。您給它一個函數和一個集合,並且它返回一個包含該集合中所有項目的映射,並將f值應用到每個值的結果中。

> (group-by #(rem 20 %) [1 2 3 4 5 6 7 8 9 10]) 
{0 [1 2 4 5 10], 2 [3 6 9], 6 [7], 4 [8]} 

如果你想的按鍵的實際關鍵字,你就必須修改匿名函數來回饋關鍵字:

> (group-by #(keyword (str (rem 20 %))) [1 2 3 4 5 6 7 8 9 10]) 
{:0 [1 2 4 5 10], :2 [3 6 9], :6 [7], :4 [8]} 

注意,返回值是向量。這是因爲您無法映射到單個鍵上的兩個項目(即映射編碼函數)。

迭代/列表綜合

現在,這一切說,我不知道這是你在找什麼。你問,「有人能幫助我理解如何獨立使用列表元素,然後如何返回20被分割的元素,並返回剩餘的元素?」這聽起來像是我的情況for。你的目的,你可以把它作爲迭代,但它真的做listcomprehension

(for [i [1 2 3 4 5 6 7 8 9 10]] 
    (list (rem 20 i) i)) 

再次,如果你真的想使用的關鍵字,而不是值,那麼你可以做:

(for [i [1 2 3 4 5 6 7 8 9 10]] 
    (list (keyword (str (rem 20 i))) i)) 

在這種特殊情況下,如凱爾指出,你可能只是用地圖:

(map #(list (keyword (str (rem 20 %))) 
      %) 
    [1 2 3 4 5 6 7 8 9 10]) 

如果你不喜歡這些返回的嵌套結構,你可以使用它們的flatten

過濾

但我還是不知道你想要使用此方法解決你的問題。在你的評論中,你有「分離結果列表,只返回0的餘數。」這聽起來像是對我來說filter,作爲副作用是懶惰的情況。

> (filter #(zero? (rem 20 %)) [1 2 3 4 5 6 7 8 9 10]) 
(1 2 4 5 10) 

Ta-da。它只是吐出滿足您需求的原始集合的元素。

希望這會有所幫助。它並沒有讓你一路走向你的目標,但我希望它能爲你提供一些可以用來達到目的的簡潔工具。你有選擇!在你學習的同時,玩弄多種選擇。如果你讀到某個地方比另一個更可取的地方,看看你是否能找出原因。

+0

謝謝你,這非常有幫助。 – dmbennett 2014-10-08 01:23:14

2
(map #(vector (rem 20 %) %) (range 1 21)) 
;; => ([0 1] [0 2] [2 3] ... [1 19] [0 20]) 

不過,我有一個非常困難的時期剛剛搞清楚如何通過列表

要重複迭代,使用高階函數類似clojure.core/map

返回20除以的元素,如果它返回餘數

你想返回2件事情。提供給clojure.core/mapfn可以通過返回兩個元素的向量來完成此操作。

爲了確定其餘的,使用rem

鍵入到其餘則返回

因爲可能有多個操作返回相同的部分,我們不能創建一個映射({})和使用剩下的作爲一個關鍵 - 會有碰撞。

clojure.core/range用於創建分母的集合。

要不太明確,使用clojure.core/juxt,下面的完成相同:

(map (juxt (partial rem 20) identity) (range 1 21)) 

最後,參數化這件事,並返回一個懶惰的序列:

(defn rem-denominator 
    [n] 
    (map (juxt (partial rem n) identity) 
     (iterate inc 1))) 

(take 5 (rem-denominator 20)) 
;; => ([0 1] [0 2] [2 3] [0 4] [0 5]) 
(take 20 (rem-denominator 20)) 
;; => ([0 1] [0 2] [2 3] ... [1 19] [0 20]) 
+0

非常好的代碼,但你可能想寫一個解釋。 – TheBat 2014-10-07 15:42:06