- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想将一个序列拆分为前 n 个元素和其余元素。这是使用内置排序和分割的低效实现:
> (defn split-top-n
[n comp coll]
(split-at n (sort comp coll)))
> (split-top-n 2 #(- %2 %1) (list 6.2 5.1 88.0 90.1 1.2 16.9))
[(90.1 88.0) (16.9 6.2 5.1 1.2)]
是否有一个高效的 Clojure 内置功能?还是我需要自己写?
最佳答案
标准库中没有这样的函数。您已经编写的简单实现实际上仅对于 n
值较小的特殊情况效率较低,但在一般情况下完全没问题。
只要您不知道当前实现中的此函数确实是整个应用程序中的一个重要性能瓶颈,那么编写更复杂的版本可能就是浪费精力。
编辑:更多地考虑这一点,可能值得尝试编写一个实现,将序列强制转换为向量,然后进行就地快速选择将 n
个最佳元素划分到向量的开头。这应该相对容易做到,并且只要精心选择枢轴元素,就可以提供合理的更好性能。
编辑 2:我决定亲自尝试该实现。它在一些简单的测试用例中运行良好,但我不完全确定其中不存在可能在某些边缘情况下触发的逐一错误:
(defn split-top-n
[n comp coll]
(let [v (transient (vec coll))]
(loop [start 0, end (count v)]
(when (> end n)
(let [pos (loop [i (inc start), pos start]
(if (< i end)
(if (comp (v i) (v start))
(let [pos* (inc pos)]
(assoc! v, i (v pos*), pos* (v i))
(recur (inc i) pos*))
(recur (inc i) pos))
(do
(assoc! v, start (v pos), pos (v start))
pos)))]
(if (< pos n)
(recur (inc pos) end)
(recur start pos)))))
(split-at n (persistent! v))))
澄清:这需要一个用于 comp
的简单 bool 比较器函数,而不是负数/零/正数类型之一。
编辑3:我再次查看了 transient 的文档,发现我正在利用未定义的行为。实际上,上述版本可能始终按预期工作,但正确的版本仍然应该尊重语言文档。我将保留此答案中的先前版本,因为答案已被接受,但这里的版本按照文档要求使用 assoc!
的返回值:
(defn swap-in!
[v i j]
(assoc! v, i (v j), j (v i)))
(defn quickpartition!
[comp v start end]
(loop [v v, i (inc start), pos start]
(if (< i end)
(if (comp (v i) (v start))
(recur (swap-in! v i (inc pos)) (inc i) (inc pos))
(recur v (inc i) pos))
[(swap-in! v start pos) pos])))
(defn split-top-n
[n comp coll]
(loop [v (transient (vec coll)), start 0, end (count v)]
(if (> end n)
(let [[v* pos] (quickpartition! comp v start end)]
(if (< pos n)
(recur v* (inc pos) end)
(recur v* start pos)))
(split-at n (persistent! v)))))
编辑4:早期版本的可读性差仍然让我心痒痒,所以我现在将我的实现分成多个函数。
关于Clojure:将序列拆分为前n个序列和其余序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18739617/
为什么该语言的名称是“Clojure”? 我用谷歌搜索了一下,在#clojure 中询问。到目前为止,还没有运气。 最佳答案 Rich Hickey(他是 Clojure 的设计者)对此的评论是 wi
我不明白为什么升级后会出现以下编译错误: Compiling addr-verify.core Exception in thread "main" java.lang.NoClassDefFound
我试图将从映射操作返回的(惰性)序列传递给另一个映射操作,以便我可以在第一个序列中查找元素。代码从文本文件(以行/列格式)解析一些足球装置,清理它,然后返回一张 map 。 这是代码: (ns fix
我想过滤一组,例如: (filter-set even? #{1 2 3 4 5}) ; => #{2 4} 如果我使用clojure.core/filter我得到一个不是集合的seq: (filte
(defn hi[](+ 5 6)) (hi) (defn hi[](+ 6 7)) (hi) 你好,我是 clojure 的新手。如上所述,我编写了两个具有相同名称的函数。我们可以在 cloj
我按照这个伪代码递归地将十进制转换为二进制。 findBinary(decimal) if (decimal == 0) binary = 0 else binar
我正在尝试学习 Clojure 并尝试定义这个简单的函数: user=> (defn triple [arg] (* 3 arg)) #'user/triple user=> (triple 1) 3
是->和 ->>宏只是为了使代码更具可读性还是它们还有其他特定功能? 最佳答案 线程优先( -> )和线程最后( ->> )是为了使代码更具可读性。但这已经很重要了! 它允许取消嵌套函数调用(示例取自
我在 http://www.learningclojure.com/2010/11/yet-another-way-to-write-factorial.html 上找到了这个代码,但我不明白 pop
我正在阅读 Programming Clojure 2nd edition,在第 49 页它涵盖了 Clojure 的 for 循环结构,它说它实际上是一个序列理解。 作者建议使用以下代码: (def
Clojure 中有双端队列吗?我的印象是 Clojure 的 PersistentQueue 是单端的(我错了吗?)。我需要能够从队列的任一端删除(即“pop”)和“peek”数据。我所说的双端队列
换句话说,有没有办法在看起来不像 (MACRO arg* ...) 的表单上触发宏扩展? . 举一个假设的例子: (defmacro my-var (do (printf "Using my-va
我很难理解懒惰。 有人能帮我理解为什么我下面的函数不是懒惰的吗 (defn my-red ([f coll] (my-red f (first coll) (rest coll) ))
在 Clojure 核心中决定参数函数顺序的规则是什么(如果有的话)? 类似 map 的函数和 filter期望数据结构作为最后一个 争论。 类似 assoc 的函数和 select-keys期待数据
我在 clojuredocs 上遇到过 completing 函数,但目前没有文档。 你能提供一些例子吗? 最佳答案 completing 用于扩充可能没有具有一元“完成”元数的一元重载的二元归约函数
这个现在支持吗?我能找到的唯一信息是来自维基的示例( https://github.com/clojure/core.match/wiki/Deftype-and-defrecord-matching
我正在关注“Clojure in Action”,对此我感到困惑: (defn with-log [function-to-call log-statement ] (fn [& args
对于下面的代码,箭头是宏还是函数名称中的简单字符? (来自 here) (defn file->map [file] ;; TODO ) 最佳答案 箭头是函数名称的一部分。有一个函数定义,不是
Clojure 的 range函数包含来自 start独家在end (如果提供)。核心库中是否有一个函数可以提供完全包含(开始和结束)的范围? 我发现在某些情况下必须调整最终值的代码 - 例如向下而不
当我尝试从 REPL 运行以下代码时(使用动态记录): (defrecord (symbol "rec2") (vec (map symbol ["f1" "f2"]))) 我收到错误 Compile
我是一名优秀的程序员,十分优秀!