2013-09-06 14 views
6

Co znajduje się idiomatyczne drogę w Clojure wdrożyć take-while-and-n-more poniżej:Clojure starcie podczas i n więcej elementów

=> (take-while-and-n-more #(<= % 3) 1 (range 10)) 
(0 1 2 3 4) 

My try to:

(defn take-while-and-n-more [pred n coll] 
    (let 
     [take-while-result (take-while pred coll) 
     n0 (count take-while-result)] 
    (concat 
    take-while-result 
    (into [] (take n (drop n0 coll)))))) 

Odpowiedz

9

użyłbym split-with, który jest odpowiednikiem uzyskanie wyników zarówno Take-czas i drop-a dla tych samych parametrów:

(defn take-while-and-n-more [pred n coll] 
    (let [[head tail] (split-with pred coll)] 
     (concat head (take n tail)))) 
1

Poniższy kod jest zmodyfikowaną wersją Clojures take-while . Tam, gdzie Clojures take-while zwraca nil jako domyślny przypadek (gdy predykat nie pasuje), ten wywołuje take, aby pobrać dodatkowe elementy po niepowodzeniu predykatu.

Należy zauważyć, że w przeciwieństwie do wersji używających split-with, ta wersja wykonuje sekwencję tylko raz.

(defn take-while-and-n-more 
    [pred n coll] 
    (lazy-seq 
    (when-let [s (seq coll)] 
    (if (pred (first s)) 
     (cons (first s) (take-while-and-n-more pred n (rest s))) 
     (take n s))))) 
+0

concat zwraca leniwą sekwencję – soulcheck

+0

Masz rację. Edytowałem swoją odpowiedź. Mimo to split-with spowoduje dwukrotne przeszukanie zgodnej z predykatem części sekwencji. –

3

jeszcze inny sposób:

(defn take-while-and-n-more [pred n coll] 
    (let [[a b] (split-with pred coll)] 
    (concat a (take n b)))) 
Powiązane problemy