Clojure: индекс значения в списке или другой коллекции - PullRequest
4 голосов
/ 11 ноября 2011

Как получить индекс любого из элементов в списке строк следующим образом:

(list "a" "b" "c")

Например, (function "a") должен будет возвращать 0, (function "b") 1, (function "c") 2 и т. Д.

и ... будет ли лучше использовать какой-либо другой тип сбора при работе с очень длинным списком данных?

Ответы [ 7 ]

7 голосов
/ 11 ноября 2011

Ответ Кристиана Берга в порядке. Также можно просто использовать метод Java indexOf класса String:

(.indexOf (appl­y str (list­ "a" "b" "c"))­ "c")

; => 2

Конечно, это будет работать только со списками (или более общими, последовательностями) строк (длиной 1) или символов.

Более общий подход:

(defn index-of [e coll] (first (keep-indexed #(if (= e %2) %1) coll)))

Более идиоматично было бы лениво возвращать все индексы и запрашивать только те, которые вам нужны:

(defn indexes-of [e coll] (keep-indexed #(if (= e %2) %1) coll)) 

(first (indexes-of "a" (list "a" "a" "b"))) ;; => 0
7 голосов
/ 11 ноября 2011

Я не уверен, что понимаю ваш вопрос. Вы хотите n-ую букву каждой из строк в списке? Это можно сделать так:

(map #(nth % 1) (list "abc" "def" "ghi"))

Результат:

(\b \e \h)

Обновление

После прочтения вашего комментария к моему первоначальному ответу, я предполагаю, что ваш вопрос звучит так: «Как мне найти индекс (позицию) строки поиска в списке?»

Одной из возможностей является поиск строки в начале списка и подсчет всех записей, которые необходимо пропустить:

(defn index-of [item coll]
  (count (take-while (partial not= item) coll)))

Пример: (index-of "b" (list "a" "b" "c")) возвращает 1.

Если вам нужно много разыскивать, может быть более эффективно построить hash-map всех строк и их индексов:

(def my-list (list "a" "b" "c"))
(def index-map (zipmap my-list (range)))
(index-map "b") ;; returns 1

Обратите внимание, что с приведенными выше определениями, когда в списке есть повторяющиеся записи, index-of вернет индекс first , а index-map вернет last .

3 голосов
/ 16 июня 2016

Вы можете надежно использовать метод Java .indexOf для строк и векторов, но не для списков.Это решение должно работать для всех коллекций, я думаю:

(defn index-of 
  "Clojure doesn't have an index-of function. The Java .indexOf method 
  works reliably for vectors and strings, but not for lists. This solution
  works for all three."
  [item coll]
  (let [v (if 
            (or (vector? coll) (string? coll)) 
            coll 
            (apply vector coll))]
    (.indexOf coll item)))
1 голос
/ 05 апреля 2014

Это ответ на Lispy, я подозреваю, что эксперт в Clojure мог бы сделать это лучше:

(defn position 
    "Returns the position of elt in this list, or nil if not present"
    ([list elt n]
        (cond
            (empty? list) nil
            (= (first list) elt) n
            true (position (rest list) elt (inc n))))
    ([list elt]
        (position list elt 0)))
1 голос
/ 11 ноября 2011

Кошачья шкура это весело. Вот низкоуровневый подход.

(defn index-of
  ([item coll]
    (index-of item coll 0))
  ([item coll from-idx]
    (loop [idx from-idx coll (seq (drop from-idx coll))]
      (if coll
        (if (= item (first coll))
          idx
          (recur (inc idx) (next coll)))
        -1))))
1 голос
/ 11 ноября 2011

Вы имеете в виду, как получить n-й элемент списка?

Например, если вы хотите получить 2-й элемент в списке (с нулевым индексом):

(nth (list "a" "b" "c") 2)

урожайность

"c"
0 голосов
/ 11 ноября 2011

Кажется, вы хотите использовать функцию nth.

Из документов для этой функции:

clojure.core/nth
([coll index] [coll index not-found])
  Returns the value at the index. get returns nil if index out of
  bounds, nth throws an exception unless not-found is supplied.  nth
  also works for strings, Java arrays, regex Matchers and Lists, and,
  in O(n) time, for sequences.

Это последнее предложение означает, что на практике nth медленнее для элементов, находящихся "дальше" в последовательностях, без гарантии более быстрой работы для коллекций, которые в принципе поддерживают более быстрый доступ (~ O (n)) к индексированным элементам. Для (замыкающих) последовательностей это имеет смысл; API clojure seq основан на API связанного списка, и в связанном списке вы можете получить доступ к n-му элементу, пройдя каждый элемент перед ним. Именно это ограничение делает конкретные реализации списков взаимозаменяемыми с ленивыми последовательностями.

Функции доступа к коллекции Clojure обычно создаются таким образом; функции, которые имеют значительно лучшее время доступа к определенным коллекциям, имеют отдельные имена и не могут использоваться «случайно» в медленных коллекциях.

В качестве примера типа коллекции, который поддерживает быстрый «произвольный» доступ к элементам, векторы замыкания могут вызываться; (индекс-номер коллекции векторов) возвращает элемент с индексом-индексом - и обратите внимание, что последующие последовательности не могут быть вызваны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...