2012-04-17 8 views
40

fnをtrueと評価するシーケンスの最初の要素を返す関数を探しています。例:trueを返す関数を満たすmap/list/sequenceの最初の項目を返します。

(first-map (fn [x] (= x 1)) '(3 4 1)) 

上記の偽関数は1(リストの最後の要素)を返す必要があります。 Clojureにはこういうものがありますか?

+7

'(first(filter#(%1) '(3 4 1))'? – 4e6

+0

@ 4e6リストのすべての要素に関数を適用するので、大きなリストでは望ましくない。 – Matthew

+10

地図は怠惰なので、私はそうは思わないと思います。 – Bill

答えて

50
user=> (defn find-first 
     [f coll] 
     (first (filter f coll))) 
#'user/find-first 
user=> (find-first #(= % 1) [3 4 1]) 
1 

編集:同時実行。 :)いいえ、それはf全体のリストに適用されません。 filterの怠惰のために最初の一致するものまでの要素にのみ。

+3

ありがとうございます@kotarak、私の懸念は、これはコレクション内のすべての要素を処理することで、大きなリストでは望ましくありません。おそらく、条件を満たす条件を見つけるまで繰り返される関数を作成する必要があります。 – Matthew

+1

あなたの編集が表示されます。ありがとうございます。 – Matthew

+4

@Matthewのモジュロチャンクシーケンス。fに応じてより多くの要素が適用されますチャンクサイズ。 – kotarak

8

私はsomeが仕事に最適なツールだと思います:#{1}はリテラル集合である:あなたのケースでは

(some #(if (= % 1) %) '(3 4 1)) 
+1

これは、チャンクされたシーケンスの影響を受けません。しかし '1'が' 'nil''や' 'false''の場合には動作しません。 YMMV。 – kotarak

+0

待って...どうすれば1はゼロになりますか? :)とにかく、Matthewは要素が「真であると評価する」べきだと指定したので、その振る舞いが望ましいと思います。 – vemv

+3

'f'が'#(#?{0 "の偽"偽}%) 'を含むと考えてください。そして、彼は「fnを真と評価する」と言った。 – kotarak

40

、イディオムがどのように動作する

(some #{1} [1 2 3 4]) 

です。 setはargが集合にあればargを評価し、そうでなければnilにする関数でもあります。どんなセット要素も "真実"値です(もちろん、ブール値の偽を除きますが、それはセットの希少性です)。 someは、結果が真実であった最初のコレクション・メンバーに対して評価された述部の戻り値を戻します。

3

使う代わりに、チャンクシーケンスのための「オーバーアプリケーション」fの対処すべきfilterdrop-while:私はいくつかのベンチマークテストを(JDK 8とのClojure 1.7)このスレッドで述べたいくつかの方法を試みたが、やった

(defn find-first [f coll] 
    (first (drop-while (complement f) coll))) 
;;=> #'user/find-first 

(find-first #(= % 1) [3 4 1]) 
;;=> 1 
10

repl> (defn find-first 
     [f coll] 
     (first (filter f coll))) 
#'cenx.parker.strategies.vzw.repl/find-first 

repl> (time (find-first #(= % 50000000) (range))) 
"Elapsed time: 5799.41122 msecs" 
50000000 

repl> (time (some #{50000000} (range))) 
"Elapsed time: 4386.256124 msecs" 
50000000 

repl> (time (reduce #(when (= %2 50000000) (reduced %2)) nil (range))) 
"Elapsed time: 993.267553 msecs" 
50000000 

結果はreduce方法は、Clojureの1.7のように、最も効率的なソリューションであり得ることを示しています。

+1

非常に興味深い。これらをテストしてくれてありがとう、xando。 [Criterium](https://github.com/hugoduncan/criterium)からの数字がある方が良いと思うのですが、私の推測によれば、シーケンス内のこれまでの項目を検索すると、JVMはコードを最適化する。 – Mars

関連する問題