How do I find the index of an item in a vector?

后端 未结 8 1875
孤独总比滥情好
孤独总比滥情好 2020-11-29 01:13

Any ideas what ???? should be? Is there a built in? What would be the best way to accomplish this task?

(def v [\"one\" \"two\" \"three\" \"two         


        
相关标签:
8条回答
  • 2020-11-29 01:22

    As of Clojure 1.4 clojure.contrib.seq (and thus the positions function) is not available as it's missing a maintainer: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

    The source for clojure.contrib.seq/positions and it's dependency clojure.contrib.seq/indexed is:

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

    Available here: http://clojuredocs.org/clojure_contrib/clojure.contrib.seq/positions

    0 讨论(0)
  • 2020-11-29 01:22

    I'd go with reduce-kv

    (defn find-index [pred vec]
      (reduce-kv
        (fn [_ k v]
          (if (pred v)
            (reduced k)))
        nil
        vec))
    
    0 讨论(0)
  • 2020-11-29 01:24

    Stuart Halloway has given a really nice answer in this post 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)
    

    If you wish to grab the first value just use first on the result.

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

    EDIT: Because clojure.contrib.seq has vanished I updated my answer with an example of a simple implementation:

    (defn positions
      [pred coll]
      (keep-indexed (fn [idx x]
                      (when (pred x)
                        idx))
                    coll))
    
    0 讨论(0)
  • 2020-11-29 01:25

    Here's my contribution, using a looping structure and returning nil on failure.

    I try to avoid loops when I can, but it seems fitting for this problem.

    (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)))))
    
    0 讨论(0)
  • 2020-11-29 01:26
    (defn find-thing [needle haystack]
      (keep-indexed #(when (= %2 needle) %1) haystack))
    

    But I'd like to warn you against fiddling with indices: most often than not it's going to produce less idiomatic, awkward Clojure.

    0 讨论(0)
  • 2020-11-29 01:30

    Built-in:

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

    If you want a lazy seq of the indices for all matches:

    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)
    
    0 讨论(0)
提交回复
热议问题