Is there a fast way to check if a sequence has exactly 1 element in Clojure? Note that a sequence may contain nils.
If I'm reading the source correctly, calling count on a sequence takes O(n) time.
Alternate solution:
(and
  (not (empty? a-seq))
  (empty? (rest a-seq)))
Docs say that calling empty? on collection coll is the same as calling (not (seq coll)), but they don't specify its efficiency or what happens when you call empty? on a sequence. I tried to search the github repository for how empty? was implemented, but it was ignoring the question mark in searches and there was a ton of hits on "empty". I would imagine empty? and rest are O(1), but then again, count wasn't...
Because
user=> (empty? (cycle [1]))
false
(the fact that the function terminates), I assume empty? evaluates in constant time, namely, (seq coll) initialises a sequence in constant time.
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
Your code does the thing rather well. Maybe I'd say:
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
                        The following function was added in 1.9 (which is still alpha as of now):
(defn bounded-count
  "If coll is counted? returns its count, else will count at most the first n
  elements of coll using its seq"
  {:added "1.9"}
  [n coll]
  (if (counted? coll)
    (count coll)
    (loop [i 0 s (seq coll)]
      (if (and s (< i n))
        (recur (inc i) (next s))
        i))))
So I guess a (bounded-count 2 coll) should give you a constant time count for what you need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With