【发布时间】:2014-08-15 09:22:29
【问题描述】:
在 Clojure 中,Java 互操作为我们提供了 .indexOf,但 ClojureScript 没有。如何获取向量中某项的索引?
(def items [:a :b :c])
;; Clojure
(.indexOf items :a) ; => 0
;; ClojureScript
;; ???
【问题讨论】:
标签: clojure clojurescript
在 Clojure 中,Java 互操作为我们提供了 .indexOf,但 ClojureScript 没有。如何获取向量中某项的索引?
(def items [:a :b :c])
;; Clojure
(.indexOf items :a) ; => 0
;; ClojureScript
;; ???
【问题讨论】:
标签: clojure clojurescript
这是一个明确的递归答案。不过我希望有更好的答案!
(defn index-of [s v]
(loop [idx 0 items s]
(cond
(empty? items) nil
(= v (first items)) idx
:else (recur (inc idx) (rest items)))))
【讨论】:
将向量转换为数组。 http://clojuredocs.org/clojure_core/clojure.core/to-array
我不确定这方面的性能如何。 :)
cljs.user=> (.indexOf (to-array [:a :b]) :b)
=> 1
【讨论】:
(.indexOf (to-array [:a :b]) :b) 返回 -1
Clojurescript 似乎没有明确的 index-of 方法(至少不是我可以通过合理的谷歌搜索找到的方法)。
对于您的示例,您可以将 clojurescript 数据结构映射到 javascript 数组并使用本机 javascript .indexOf
=> (.indexOf (clj->js [:a :b :c :d]) (clj->js :c))
=> 2
但是这样做有两个问题,首先你必须离开持久数据结构的世界,这是使 clojurescript 伟大的重要部分,但更大的问题是它不适用于引用类型。例如
=> (.indexOf (clj->js [{:a :b} {:c :d}]) (clj->js {:c :d}))
=> -1
所以它的用途有限。
在这种情况下,您自己的递归解决方案是一个很好的解决方案。如果你想要更实用的东西,你可以这样做:
(defn index-of [coll v]
(let [i (count (take-while #(not= v %) coll))]
(when (or (< i (count coll))
(= v (last coll)))
i)))
【讨论】:
另一个选项(如果未找到则返回 nil)
(defn index-of [coll value]
(some (fn [[idx item]] (if (= value item) idx))
(map-indexed vector coll)))
【讨论】: