作为Clojure的新手,我经常很难表达最简单的东西。例如,要替换向量中的最后一个元素,将是

v[-1]=new_value

在python中,我最终在Clojure中使用以下变体:
(assoc v (dec (count v)) new_value)

至少可以说这很长而且毫无表情,或者
(conj (vec (butlast v)) new_value)

更糟糕的是,它具有O(n)运行时间。

这让我感到很傻,就像一个穴居人试图用俱乐部修理瑞士表一样。

Clojure替换向量中最后一个元素的正确方法是什么?

为了支持我的O(n) -version(Clojure 1.8)的butlast -claim:
(def v (vec (range 1e6)))
#'user/v
user=> (time (first (conj (vec (butlast v)) 55)))
"Elapsed time: 232.686159 msecs"
0
(def v (vec (range 1e7)))
#'user/v
user=> (time (first (conj (vec (butlast v)) 55)))
"Elapsed time: 2423.828127 msecs"
0

因此,基本上10倍的元素数量要慢10倍。

最佳答案

我会用

(defn set-top [coll x]
  (conj (pop coll) x))

例如,
(set-top [1 2 3] :a)
=> [1 2 :a]

但它也适用于列表的最前面:
(set-top '(1 2 3) :a)
=> (:a 2 3)

Clojure堆栈函数peekpopconj-在顺序集合的自然开放端工作。

但是,没有一种正确的方法。

各种解决方案如何对空向量作出 react ?
  • 您的Python v[-1]=new_value会引发异常,您的(assoc v (dec (count v)) new_value)和我的(defn set-top [coll x] (conj (pop coll) x))也会引发异常。
  • 您的(conj (vec (butlast v)) new_value)返回[new_value]butlast无效。
  • 10-07 19:27
    查看更多