Как найти индекс элемента в векторе?



любые идеи, что ???? должно быть? Есть ли встроенный?
Каков был бы лучший способ выполнить эту задачу?



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

7 ответов:

встроенный:

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)

Стюарт Хэлоуэй дал действительно хороший ответ в этом посте http://www.mail-archive.com/[email protected]/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))
(defn find-thing [needle haystack]
  (keep-indexed #(when (= %2 needle) %1) haystack))

но я хотел бы предостеречь вас от возиться с индексами: чаще всего это будет производить менее идиоматичный, неудобный Clojure.

по состоянию на Clojure 1.4 clojure.ВНО.СЛ (и, таким образом,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

Я пытался ответить на свой собственный вопрос, но Брайан опередил меня с ответом!

(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

недавно мне пришлось найти индексы несколько раз или, скорее, я выбрал, так как это было проще, чем выяснить другой способ подхода к проблеме. По пути я обнаружил, что в моих списках 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)))))

вот мой вклад, используя loop ing структура и возврат 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)))))

Comments

    Ничего не найдено.