Подтвердить что ты не робот

Найти индекс элемента, соответствующего предикату в Clojure?

С Clojure, как мне найти первый индекс с положительным значением в этом векторе [-1 0 3 7 9]?

Я знаю, что вы можете получить первый результат чего-то довольно элегантно с помощью first и filter:

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

Этот код возвращает значение 99. Ответ, который я хочу, - это индекс 2.

4b9b3361

Ответ 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-indexedindices) вся последовательность не должна быть реализована, поэтому не выполняются посторонние вычисления.

Ответ 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