7 ответов:
встроенный:
user> (def v ["one" "two" "three" "two"]) #'user/v user> (.indexOf v "two") 1 user> (.indexOf v "foo") -1Если вы хотите ленивый seq индексов для всех матчей:
user> (map-indexed vector v) ([0 "one"] [1 "two"] [2 "three"] [3 "two"]) user> (filter #(= "two" (second %)) *1) ([1 "two"] [3 "two"]) user> (map first *1) (1 3) user> (map first (filter #(= (second %) "two") (map-indexed vector v))) (1 3)
Стюарт Хэлоуэй дал действительно хороший ответ в этом посте http://www.mail-archive.com/[email protected]/msg34159.html.
(use '[clojure.contrib.seq :only (positions)]) (def v ["one" "two" "three" "two"]) (positions #{"two"} v) ; -> (1 3)если вы хотите, чтобы захватить первое значение просто используйте
firstна результат.(first (positions #{"two"} v)) ; -> 1редактировать: потому что
clojure.contrib.seqисчез я обновил свой ответ с примером простой реализации:(defn positions [pred coll] (keep-indexed (fn [idx x] (when (pred x) idx)) coll))
(defn find-thing [needle haystack] (keep-indexed #(when (= %2 needle) %1) haystack))но я хотел бы предостеречь вас от возиться с индексами: чаще всего это будет производить менее идиоматичный, неудобный Clojure.
по состоянию на Clojure 1.4 clojure.ВНО.СЛ (и, таким образом,
positionsфункция) недоступна, так как отсутствует сопровождающий: http://dev.clojure.org/display/design/Where+Did+Clojure. Contrib + Goисточник
clojure.contrib.seq/positionsи это зависимостьclojure.contrib.seq/indexed- это:(defn indexed "Returns a lazy sequence of [index, item] pairs, where items come from 's' and indexes count up from zero. (indexed '(a b c d)) => ([0 a] [1 b] [2 c] [3 d])" [s] (map vector (iterate inc 0) s)) (defn positions "Returns a lazy sequence containing the positions at which pred is true for items in coll." [pred coll] (for [[idx elt] (indexed coll) :when (pred elt)] idx)) (positions #{2} [1 2 3 4 1 2 3 4]) => (1 5)здесь: http://clojuredocs.org/clojure_contrib/clojure.contrib.seq/positions
Я пытался ответить на свой собственный вопрос, но Брайан опередил меня с ответом!
(defn indices-of [f coll] (keep-indexed #(if (f %2) %1 nil) coll)) (defn first-index-of [f coll] (first (indices-of f coll))) (defn find-thing [value coll] (first-index-of #(= % value) coll)) (find-thing "two" ["one" "two" "three" "two"]) ; 1 (find-thing "two" '("one" "two" "three")) ; 1 ;; these answers are a bit silly (find-thing "two" #{"one" "two" "three"}) ; 1 (find-thing "two" {"one" "two" "two" "three"}) ; nil
недавно мне пришлось найти индексы несколько раз или, скорее, я выбрал, так как это было проще, чем выяснить другой способ подхода к проблеме. По пути я обнаружил, что в моих списках Clojure этого не было .метод indexOf (Object object, int start). Я справился с проблемой так:
(defn index-of "Returns the index of item. If start is given indexes prior to start are skipped." ([coll item] (.indexOf coll item)) ([coll item start] (let [unadjusted-index (.indexOf (drop start coll) item)] (if (= -1 unadjusted-index) unadjusted-index (+ unadjusted-index start)))))
вот мой вклад, используя
looping структура и возвратnilна провал.Я стараюсь избегать петель, когда я могу, но это кажется подходящим для этой проблемы.
(defn index-of [xs x] (loop [a (first xs) r (rest xs) i 0] (cond (= a x) i (empty? r) nil :else (recur (first r) (rest r) (inc i)))))
Comments