Collections 基于谓词排序的库函数
Clojure库中是否存在用于筛选集合并返回一对集合的函数,其中一个包含谓词返回true的项,另一个包含谓词返回false的项 例如:Collections 基于谓词排序的库函数,collections,clojure,Collections,Clojure,Clojure库中是否存在用于筛选集合并返回一对集合的函数,其中一个包含谓词返回true的项,另一个包含谓词返回false的项 例如: (let [[yays nays] (some-fn pred coll)] ... ) 或多或少,我在寻找一种基于谓词排序的方法,而不是丢弃(比如使用过滤器或删除) (注意:我知道一个解决方案是分别对集合调用filter和remove;我只想知道是否有一个内置函数可以更有效地实现这一点) (编辑:seq utils/separate不符合效率更高的条件。它会
(let [[yays nays] (some-fn pred coll)] ... )
或多或少,我在寻找一种基于谓词排序的方法,而不是丢弃(比如使用过滤器或删除)
(注意:我知道一个解决方案是分别对集合调用filter
和remove
;我只想知道是否有一个内置函数可以更有效地实现这一点)
(编辑:seq utils/separate
不符合效率更高的条件。它会对每个项目对谓词求值两次。)如果您希望获得最大性能,您需要使用循环/重复来实现这一点,例如:
(defn separate-by [pred coll]
(loop [yays nil
nays nil
s (seq coll)]
(if s
(let [item (first s)
test (pred item)]
(if test
(recur (conj yays item) nays (next s))
(recur yays (conj nays item) (next s))))
{:yays yays :nays nays})))
这是最有效的原因,因为循环/递归使您能够迭代地构建两个输出列表,而无需任何额外的内存分配(例如,如果您重复更新映射,就会发生这种情况)或引用开销(如果使用两个原子来累积结果,就会发生这种情况).这会颠倒输入序列的顺序,这通常是意外的副作用。最好从[]
开始,而不是从nil
开始。但这肯定是最快的方法:我看不到任何低效。但是请注意,@scrapdog,这个解决方案不是懒惰的(我也不是)。任何既懒惰又不可变的解决方案都必须遍历序列两次。