我如何find一个vector中的项目的索引?
任何想法什么????
应该? 有内置的吗? 什么是完成这个任务的最好方法?
(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
内置:
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)
Stuart Halloway在这篇文章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)
如果您希望获取第一个值,请首先使用结果。
(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.contrib.seq(因此positions
function)不可用,因为它缺less一个维护者: 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 '(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)
可在这里find: http : //clojuredocs.org/clojure_contrib/clojure.contrib.seq/positions
我试图回答我自己的问题,但是Brian用更好的答案来打败我。
(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
我最近不得不多次find索引,或者宁愿select索引,因为比找出解决问题的另一种方法更容易。 一路上我发现我的Clojure列表没有.indexOf(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)))))
这是我的贡献,使用loop
结构,并在失败时返回nil
。
我尽量避免循环,但似乎适合这个问题。
(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)))))