Милый, спасибо, Брайан, мой искатель документов не нашел indexOf, предположительно потому, что это Java. Мне придется над этим поработать.
Джон Лоуренс Аспден
2
@ Джон: Да. Точка перед indexOf указывает на взаимодействие Java. Он вызывает метод indexOf в java.lang.String. java.lang импортируется по умолчанию. Дополнительные примеры см. На clojure.org/java_interop
dermatthias
25
Вызывается векторный indexOfметод, а не String:#<Method public int clojure.lang.APersistentVector.indexOf(java.lang.Object)>
@ d9k, «Если пространство имен clojure.contrib указано здесь, но не содержит подробностей миграции, это означает, что никто не вызвался поддерживать это пространство имен». Я добавил пример реализации для positions.
О, как мило «когда»! Я согласен с индексами в целом, но у меня есть файл csv, и имена полей указаны в заголовке, и я хочу получить поле «field» из каждой строки, поэтому я ищу «поле» вверх в заголовке, а затем разложите строки. Я могу придумать странные вещи, связанные с чередованием, но есть ли хороший способ, который не использует явные индексы, которые можно прочитать?
Джон Лоуренс Аспден
8
Когда у меня есть этот вариант использования - заголовки csv - я только что построил карту для поиска (предполагая уникальные заголовки столбцов). Тогда карта - это моя функция для поиска по индексу. (let [header-index (zipmap header-vector (iterate inc 0))] ...)
Алекс Стоддард
1
Вау. Вы ответили на вопрос, который я должен был задать!
Джон Лоуренс Аспден
3
Что ж, я бы предложил что-то очень похожее на решение Алекса. (-> строка индекса заголовка "colname") и у вас есть ваше значение.
Источник clojure.contrib.seq/positionsи зависимость clojure.contrib.seq/indexed:
(defnindexed"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))
(defnpositions"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} [12341234]) => (15)
Недавно мне приходилось искать индексы несколько раз, или, вернее, я решил, потому что это было проще, чем найти другой способ решения проблемы. Попутно я обнаружил, что в моих списках Clojure нет метода .indexOf (объект объекта, int start). Я разобрался с проблемой так:
(defnindex-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)))))
Ответы:
Встроенный:
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
метод, а не String:#<Method public int clojure.lang.APersistentVector.indexOf(java.lang.Object)>
Стюарт Хэллоуэй дал действительно хороший ответ в этом сообщении 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.contib.seq
в clojure 1.6? В списке нет библиотеки: dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Gopositions
.(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
источник
Я пытался ответить на свой вопрос, но Брайан опередил меня, предложив лучший ответ!
(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
источник
Вот мой вклад, использующий
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)))))
источник
Недавно мне приходилось искать индексы несколько раз, или, вернее, я решил, потому что это было проще, чем найти другой способ решения проблемы. Попутно я обнаружил, что в моих списках Clojure нет метода .indexOf (объект объекта, 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)))))
источник
Я бы пошел с редуктором
(defn find-index [pred vec] (reduce-kv (fn [_ k v] (if (pred v) (reduced k))) nil vec))
источник