有什么想法,????
应该是什么?有没有内置的方法?
完成这个任务的最佳方式是什么?
(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
有什么想法,????
应该是什么?有没有内置的方法?
完成这个任务的最佳方式是什么?
(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
如果您想获得所有匹配项的索引的延迟序列: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)
indexOf
方法,而不是字符串的:#<Method public int clojure.lang.APersistentVector.indexOf(java.lang.Object)>
。 - deprecatedStuart 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
即可。
(first (positions #{"two"} v)) ; -> 1
编辑:因为clojure.contrib.seq
已经消失,所以我更新了我的答案并提供了一个简单实现的示例:
(defn positions
[pred coll]
(keep-indexed (fn [idx x]
(when (pred x)
idx))
coll))
clojure.contrib.seq
?列表中没有库:http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go - d9k(defn find-thing [needle haystack]
(keep-indexed #(when (= %2 needle) %1) haystack))
但我想提醒你不要在索引上瞎搞:大多数情况下,这会产生不太符合惯用法的、笨拙的Clojure。
从Clojure 1.4开始,clojure.contrib.seq(因此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
我本想回答自己的问题,但是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
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)))))
最近我多次需要查找索引,或者说我选择这样做是因为这比寻找其他解决问题的方法更容易。在此过程中,我发现我的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)))))
如果我们只需要第一个索引,就不需要循环整个集合。 some
函数会在找到第一个匹配项后立即停止。
(defn index-of [x coll]
(let [idx? (fn [i a] (when (= x a) i))]
(first (keep-indexed idx? coll))))
我会选择使用 reduce-kv
(defn find-index [pred vec]
(reduce-kv
(fn [_ k v]
(if (pred v)
(reduced k)))
nil
vec))