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