2013-09-06 14 views
6

以下take-while-and-n-moreを実装するためのClojureでの慣用の方法は何ですか複数のアイテムを、しばらく時間がかかるとn:Clojureのは

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

を私の試みは、次のとおりです。

(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)))))) 

答えて

9

私は両方-しばらく時間がかかるとドロップしばらく同じパラメータについての結果取得のと同等である、split-withを使用します。さらに別の方法

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

次のコードは、Clojures take-whileの修正版です。 Clojures take-whileがデフォルトのケースとしてnilを返した場合(述語が一致しない場合)、述語が失敗した後に追加項目を取るために、これはtakeを呼び出します。

split-withを使用しているバージョンとは異なり、このバージョンはシーケンスを1回だけトラバースすることに注意してください。

(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

連結遅延シーケンスを返します – soulcheck

+0

あなたは正しいです。私は私の答えを編集しました。それでも、split-withは、シーケンスの述部に一致する部分を2回トラバースします。 –

3

を:

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