¿Cómo encuentro el índice de un artículo en un vector?

¿Alguna idea de qué ???? ¿debiera ser? ¿Hay un built-in? ¿Cuál sería la mejor manera de lograr esta tarea?

 (def v ["one" "two" "three" "two"]) (defn find-thing [ thing vectr ] (????)) (find-thing "two" v) ; ? maybe 1, maybe '(1,3), actually probably a lazy-seq 

Incorporado:

 user> (def v ["one" "two" "three" "two"]) #'user/v user> (.indexOf v "two") 1 user> (.indexOf v "foo") -1 

Si desea un seq perezoso de los índices para todos los partidos:

 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) 

Stuart Halloway ha dado una muy buena respuesta en esta publicación http://www.mail-archive.com/clojure@googlegroups.com/msg34159.html .

 (use '[clojure.contrib.seq :only (positions)]) (def v ["one" "two" "three" "two"]) (positions #{"two"} v) ; -> (1 3) 

Si desea tomar el primer valor, simplemente use first en el resultado.

 (first (positions #{"two"} v)) ; -> 1 

EDITAR: Como clojure.contrib.seq ha desaparecido, actualicé mi respuesta con un ejemplo de implementación simple:

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

Pero me gustaría advertirte que no te metas con los índices: la mayoría de las veces va a producir menos idiomática, incómoda Clojure.

A partir de Clojure 1.4 clojure.contrib.seq (y por lo tanto la función de positions ) no está disponible ya que le falta un mantenedor: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

La fuente para clojure.contrib.seq/positions y su dependencia clojure.contrib.seq/indexed es:

 (defn indexed "Returns a lazy sequence of [index, item] pairs, where items come from 's' and indexes count up from zero. (indexed '(abcd)) => ([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) 

Disponible aquí: http://clojuredocs.org/clojure_contrib/clojure.contrib.seq/positions

Estaba intentando responder mi propia pregunta, ¡pero Brian me ganó con una mejor respuesta!

 (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 

Recientemente tuve que encontrar índices varias veces o más bien elegí porque era más fácil que encontrar otra manera de abordar el problema. En el camino, descubrí que mis listas Clojure no tenían el método .indexOf (objeto Object, int start). He tratado el problema de esta manera:

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

Aquí está mi contribución, usando una estructura de loop y regresando nil en caso de falla.

Intento evitar bucles cuando puedo, pero parece apropiado para este problema.

 (defn index-of [xs x] (loop [a (first xs) r (rest xs) i 0] (cond (= ax) i (empty? r) nil :else (recur (first r) (rest r) (inc i)))))