2016-03-27 64 views
0

我無法編寫一個優雅的drop-last-bybutlast-by函數。一個謂詞爲真的集合中除最後一個元素之外的所有元素的序列

(drop-last-by odd? [2 1 9 4 7 7 3]) ; => (2 1 9 4) 
(drop-last-by odd? [2 4]) ; => (2 4) 
(drop-last-by odd? [9]) ; =>() 

我到目前爲止的工作,但似乎有點笨拙,我不知道是否可以在兩三行完成。

(defn drop-last-by [pred coll] 
    (let [p (partition-by pred coll)] 
    (apply concat (if (and (seq p) (pred (first (last p)))) 
        (butlast p) 
        p)))) 

回答

5

由於drop-while已經沒有基本上你需要什麼,因爲你目前的解決方案已經不能偷懶,我會寫drop-last-by這樣的:

(defn drop-last-by [pred coll] 
    (reverse (drop-while pred (reverse coll)))) 
1

下面的版本是懶得允許的程度由該問題規範:

  1. 不滿足謂詞的任何元件被立即穿過而不讀取任何額外的元件s來源;

  2. 只要從源讀入不滿足謂詞的元素,任何滿足謂詞的元素都會被傳遞;

  3. 任何滿足謂詞的元素都將被丟棄,並且不會跟隨其他不滿足謂詞的元素。

此外,它可以用作(有狀態)換能器;實際上懶惰的seq版本是通過傳感器和clojure.core/sequence來實現的。

(defn drop-last-by 
    ([pred] 
    (fn [rf] 
    (let [xs (volatile! [])] 
     (fn 
     ([] (rf)) 
     ([result] (rf result)) 
     ([result input] 
      (if-not (pred input) 
      (do 
       (reduce rf result @xs) 
       (vreset! xs []) 
       (rf result input)) 
      (do 
       (vswap! xs conj input) 
       result))))))) 
    ([pred coll] 
    (sequence (drop-last-by pred) coll))) 

在REPL:

(drop-last-by odd? [2 1 9 4 7 7 3]) 
;= (2 1 9 4) 
(drop-last-by odd? [2 4]) 
;= (2 4) 
(drop-last-by odd? [9]) 
;=() 

與其他傳感器組成:

(into [] 
     (comp (drop-while even?) 
      (drop-last-by odd?) 
      (map #(str "foo " %))) 
     [0 1 2 3 4 5]) 
;= ["foo 1" "foo 2" "foo 3" "foo 4"] 
相關問題