Using keep-indexed
you can get a sequence of indices for which a predicate is satisfied:
(defn indices [pred coll]
(keep-indexed #(when (pred %2) %1) coll))
With this simple function you'll solve your problem with the expression
user=> (first (indices pos? [-1 0 99 100 101]))
2
Note that, due to the lazyness of keep-indexed
(and indices
), the entire sequence need not be realized so no extraneous calculations are performed.
(defn first-pos [x]
(loop [arr x n 0]
(if (pos? (first arr))
n
(recur (next arr) (inc n)))))
This is a good example of using functional programming's powerful tail recursion.
(first (filter #(not (nil? %)) (map #(when (pos? %1) %2) [-1 1 0 99 100 101] (range))))
Map can take one or more collections and return one list,put condition on map,and filter nil.
(defn pred-idx [pred [idx hist] cur]
(if (pred cur)
[(inc idx) (conj hist idx)]
[(inc idx) hist]))
(defn idx-filter [pred col]
(second (reduce (partial pred-idx pred) [0 []] col)))
(first (idx-filter pos? [-1 0 99 100 101]))
2
Not sure if this is better, but it works. I think it forces evaluation of the entire sequence though, and if you need all indices that would be better. The correct thing to do is probably turn it into a lazy sequence somehow, but I'm done for the evening.
I'm a little late to the party, but I prefer:
(defn index-of-pred
[pred coll]
(ffirst (filter (comp pred second) (map-indexed list coll))))
;; example usage
(index-of-pred pos? [-1 -2 -5 0 3 4 1 -100])
;=> 4
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