2017-03-05 39 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

相关问题