Clojure:O(1) 函数检查序列是否恰好有 1 个元素

Att*_*nen 5 performance functional-programming predicate clojure

Clojure 中是否有一种快速方法来检查序列是否恰好有 1 个元素?请注意,序列可能包含 nils。

如果我正确读取源代码,调用count序列需要 O(n) 时间。

替代解决方案:

(and
  (not (empty? a-seq))
  (empty? (rest a-seq)))
Run Code Online (Sandbox Code Playgroud)

文档说调用empty?集合与coll调用相同(not (seq coll)),但他们没有指定其效率或调用empty?序列时会发生什么。我尝试在 github 存储库中搜索其empty?实现方式,但它忽略了搜索中的问号,并且出现了大量“空”的点击。我想empty?restO(1),但话又说回来,count不是......

unp*_*680 3

因为

user=> (empty? (cycle [1]))
false
Run Code Online (Sandbox Code Playgroud)

(函数终止的事实),我假设empty?在恒定时间内求值,即(seq coll)在恒定时间内初始化一个序列。

user=> (source empty?)
(defn empty?
  "Returns true if coll has no items - same as (not (seq coll)).
  Please use the idiom (seq x) rather than (not (empty? x))"
  {:added "1.0"
   :static true}
  [coll] (not (seq coll)))
nil
Run Code Online (Sandbox Code Playgroud)

你的代码做得很好。也许我会说:

user=> (defn single-elem? [s]
  #_=>   (and
  #_=>     (seq s)
  #_=>     (empty? (rest s))))
#'user/single-elem?

user=> (single-elem? [1])
true
user=> (single-elem? [1 2])
false
user=> (single-elem? [])
nil
user=> (single-elem? {:foo :bar})
true
user=> (single-elem? {:foo :bar :fez 42})
false
Run Code Online (Sandbox Code Playgroud)