使用 Clojure,如何找到该向量中第一个具有正值的索引
[-1 0 3 7 9]
?
我知道你可以用
first
和 filter
相当优雅地得到第一个结果:
(first (filter pos? [-1 0 99 100 101]))
此代码返回值
99
。我想要的答案是索引,即2
。
keep-indexed
您可以获得满足谓词的索引序列:
(defn indices [pred coll]
(keep-indexed #(when (pred %2) %1) coll))
通过这个简单的函数,您将用表达式解决您的问题
user=> (first (indices pos? [-1 0 99 100 101]))
2
请注意,由于
keep-indexed
(和 indices
)的惰性,不需要实现整个序列,因此不会执行任何无关的计算。
(defn first-pos [x]
(loop [arr x n 0]
(if (pos? (first arr))
n
(recur (next arr) (inc n)))))
这是使用函数式编程强大的尾递归的一个很好的例子。
(first (filter #(not (nil? %)) (map #(when (pos? %1) %2) [-1 1 0 99 100 101] (range))))
Map 可以接受一个或多个集合并返回一个列表,在 Map 上放置条件,并过滤 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
不确定这是否更好,但它确实有效。我认为它会强制评估整个序列,如果您需要所有索引那就更好了。正确的做法可能是以某种方式将其变成一个懒惰的序列,但我晚上已经完成了。
我参加聚会有点晚了,但我更喜欢:
(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
试试这个:
(defn first-index
([pred coll] (first-index coll pred 0))
([pred coll idx]
(cond (= coll '()) -1
(pred (first coll)) idx
:else (recur pred (rest coll) (inc idx)))))
并像这样使用它:
(defn is-pos? [x]
(> x 0))
(first-index is-pos? [-1 0 3 7 9])
它返回满足谓词的第一个元素的从零开始的索引(在示例中为
is-pos?
),如果没有元素与谓词匹配,则返回-1。
(defn first-idx
([pred]
(fn [coll] (first-idx pred coll)))
([pred coll]
(reduce-kv
(fn [_ idx val] (when (pred val) (reduced idx)))
nil
coll)))
(first-idx nil? [:a :b nil]) ;; ~> 2
((first-idx nil?) [:a :b :c nil]) ;; ~> 3
(first-idx nil? nil) ;; ~> nil
(first-idx nil? [:a :b :c]) ;; ~> nil