2017-03-05 8 views
3

私は、Clojureで与えられた述語を満たすシーケンスの最初の要素の最後を見つけようとしています。Clojureで与えられた述語を満たすシーケンスの最初の要素の最後を見つける方法はありますか?

は、私は、現時点で次のコードを使用します。

(last (take-while pred (gimme-potentially-infinite-seq ...))) 

残念ながら、(take-while ...)は、いくつかのケースでは、メモリ不足の私を引き起こして、頭の上に成り立ちます。

私はそれを解決するためにloop/if/recurコンボを使用することができましたが、正確にはclojure.coreにいくつかの機能(または機能の組み合わせ)がありますか?

更新:lastのように頭にかかっているのはtake-whileではありません。

更新2:私はこの(->> (range) (take 10000000) last)をClojure REPLとClojureScript REPL(Planck 2.0.0とLumo 1.1.0)でテストしました。プランク(2GBのRAM)とLumo(1.5GB)では大きなヒープの成長が見られますが、JVM(200〜300MB)ではヒープの成長がわずかです。

+0

私は何かが不足しているかもしれませんが、*無限*シーケンスで述語を満たす最後の要素を見つける方法はありますか?結果を得るには、シーケンス全体をスキャンする必要があります。 –

+0

「最後」が頭の上にあると思う理由を説明できますか?あなたの呼び出しは、一定のヒープ使用(無制限の成長なし)で私のために働きます。 – glts

+0

@gltsそれはClojureScriptのようです(上記の私の更新を見てください)。 – sickill

答えて

1

ただ、ゆっくりとそれを構築:あなたの順序が本当に無限であればもちろん

(def data (range 9999)) 
(defn is-evil? [x] 
    (= 666 (mod x 1000))) ; is the number like xxxx666 

(def all-matching-nums 
    (filter is-evil? data)) 

all-matching-nums   => (666 1666 2666 3666 4666 5666 6666 7666 8666 9666) 
(last all-matching-nums) => 9666 

を、filterステップが終了することはありません。それは別の問題です!

+1

私はそれを見ています: 'filter'ステップはいつも終わります - それは怠惰です。 [ソースコード](https://github.com/clojure/clojure/blob/clojure-1.9.0-alpha14/src/clj/clojure/core.clj#L2766)を見てください: 'レイジーシーケンス'マクロは、評価されていない関数としてそのボディをキャプチャします。フィルタリングされたシーケンスが無限である場合、 'last'は終了しません。とにかく、準拠した要素の最初の最大のサブシーケンスの最後です。配列全体の最後の準拠要素ではありません。 – Thumbnail

関連する問題