2017-03-05 68 views
3

我試圖在Clojure中找到滿足給定謂詞的序列的最後一個元素。如何找到在Clojure中滿足給定謂詞的序列的最後一個元素?

我使用下面的代碼的那一刻:

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

不幸的是,(take-while ...)持有到頭部,導致我出的內存在某些情況下。

我可以使用loop/if/recur組合來解決這個問題,但也許在clojure.core中有一些函數(或函數的組合)可以做到這一點嗎?

更新:這不是take-while這是持有的頭,但last

更新2:我在Clojure REPL和ClojureScript REPLs(Planck 2.0.0和Lumo 1.1.0)中測試了(->> (range) (take 10000000) last)。普朗克(2GB內存)和Lumo(1.5GB)的堆增長很大,而JVM(200-300MB)的堆增長較小。

+0

我可能會錯過一些東西......但是你怎麼能期望在*無限*序列中找到滿足謂詞的最後一個元素?您必須掃描整個序列才能得到結果。 –

+0

你能解釋爲什麼你認爲'last'持有頭部?您的調用適用於持續堆使用(無限制增長)。 – 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):'lazy-sequence '宏將其身體捕獲爲未評估的功能。如果過濾的序列是無限的,則「last」不會終止。無論如何,這是所需的第一個最大的順應元素子序列的最後一個;而不是整個序列的最後一個符合要素。 – Thumbnail

相關問題