在 Clojure 中查找与谓词匹配的元素的索引?

问题描述 投票:0回答:7

使用 Clojure,如何找到该向量中第一个具有正值的索引

[-1 0 3 7 9]

我知道你可以用

first
filter
相当优雅地得到第一个结果:

(first (filter pos? [-1 0 99 100 101]))

此代码返回值

99
。我想要的答案是索引,即
2

clojure
7个回答
47
投票

使用

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
)的惰性,不需要实现整个序列,因此不会执行任何无关的计算。


3
投票
(defn first-pos [x] 
  (loop [arr x n 0]
     (if (pos? (first arr))
     n
     (recur (next arr) (inc n)))))

这是使用函数式编程强大的尾递归的一个很好的例子。


1
投票
(first (filter #(not (nil? %)) (map #(when (pos? %1) %2) [-1 1 0 99 100 101] (range))))

Map 可以接受一个或多个集合并返回一个列表,在 Map 上放置条件,并过滤 nil。


1
投票
(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

不确定这是否更好,但它确实有效。我认为它会强制评估整个序列,如果您需要所有索引那就更好了。正确的做法可能是以某种方式将其变成一个懒惰的序列,但我晚上已经完成了。


1
投票

我参加聚会有点晚了,但我更喜欢:

(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

0
投票

试试这个:

(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。


0
投票
(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
© www.soinside.com 2019 - 2024. All rights reserved.