Найти индекс элемента, соответствующего предикату в Clojure?
С Clojure, как мне найти первый индекс с положительным значением в этом векторе [-1 0 3 7 9]
?
Я знаю, что вы можете получить первый результат чего-то довольно элегантно с помощью first
и filter
:
(first (filter pos? [-1 0 99 100 101]))
Этот код возвращает значение 99
. Ответ, который я хочу, - это индекс 2
.
Ответы
Ответ 1
Используя 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
) вся последовательность не должна быть реализована, поэтому не выполняются посторонние вычисления.
Ответ 2
(defn first-pos [x]
(loop [arr x n 0]
(if (pos? (first arr))
n
(recur (next arr) (inc n)))))
Это хороший пример использования мощной хвостовой рекурсии функционального программирования.
Ответ 3
(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
Не уверен, что это лучше, но он работает. Я думаю, что он заставляет оценивать всю последовательность, и если вам нужны все индексы, которые были бы лучше. Правильная вещь - это, вероятно, превратить ее в ленивую последовательность, но я закончил вечер.
Ответ 4
(first (filter #(not (nil? %)) (map #(when (pos? %1) %2) [-1 1 0 99 100 101] (range))))
Карта может принимать одну или несколько коллекций и возвращать один список, ставить условие на карту и фильтровать нуль.
Ответ 5
Попробуйте следующее:
(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, если ни один элемент не соответствует предикату.
Ответ 6
Я немного опоздал на вечеринку, но предпочитаю:
(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