ClojureScript中的矢量索引

时间:2014-08-15 09:22:30

标签: clojure clojurescript

在Clojure中,Java interop为我们提供了.indexOf,但ClojureScript并没有这样做。如何获取向量中项目的索引?

(def items [:a :b :c])

;; Clojure
(.indexOf items :a) ; => 0

;; ClojureScript
;; ???

4 个答案:

答案 0 :(得分:5)

这是一个明确的递归答案。我希望能有更好的答案!

(defn index-of [s v]
  (loop [idx 0 items s]
    (cond
      (empty? items) nil
      (= v (first items)) idx
      :else (recur (inc idx) (rest items)))))

答案 1 :(得分:5)

将矢量转换为数组。 http://clojuredocs.org/clojure_core/clojure.core/to-array

我不确定此处的性能是什么。 :)

cljs.user=> (.indexOf (to-array [:a :b]) :b)
=> 1

答案 2 :(得分:3)

Clojurescript似乎没有一个明确的index-of方法(至少不是我能用合理数量的谷歌搜索找到的方法)。

对于您的示例,您可以将clojurescript数据结构映射到javascript数组并使用原生javascript .indexOf

=> (.indexOf (clj->js [:a :b :c :d]) (clj->js :c))
=> 2

但是这有两个问题,首先你必须离开持久数据结构的世界,这是使clojurescript很棒的一个重要部分,但更大的问题是它不能在引用类型上工作。 E.g。

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

答案 3 :(得分:3)

另一个选项(如果没有找到,则返回nil)

(defn index-of [coll value]
  (some (fn [[idx item]] (if (= value item) idx))
        (map-indexed vector coll)))