Clojure: index of a value in a list or other collection

How to get the index of any of the elements in the list of lines like this:

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

For example, (function "a") would return 0, (function "b") 1, (function "c") 2, etc.

and ... would it be better to use any other type of collection if you are dealing with a very long list of data?

+4
source share
7 answers

Christian Berg's answer is fine. You can also simply indexOf back on the Java indexOf method of the String class:

 (.indexOf (apply str (list "a" "b" "c")) "c") 

; => 2

Of course, this will only work with lists (or more general, seqs) of strings (length 1) or characters.

More general approach:

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

More idiomatic would be lazy to return all indexes and only ask for the ones you need:

 (defn indexes-of [e coll] (keep-indexed #(if (= e %2) %1) coll)) (first (indexes-of "a" (list "a" "a" "b"))) ;; => 0 
+7
source

I'm not sure I understand your question. Do you need the nth letter of each line in the list? This can be done as follows:

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

Result:

 (\b \e \h) 

Update

After reading your comment on my original answer, I assume that your question is: "How to find the index (position) of a search string in a list?"

One of the possibilities is to search for the line from the beginning of the list and count all the entries that you must skip:

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

Example: (index-of "b" (list "a" "b" "c")) returns 1 .

If you need to search a lot, it may be more efficient to build a hash-map all the rows and their indices:

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

Note that with the above definitions, when there are duplicate entries in the list, index-of will return the first index, and index-map will return the last.

+7
source

You can use the Java.indexOf method reliably for strings and vectors, but not for lists. I think this solution should work for all collections:

 (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))) 
+3
source

Do you mean how do you get the nth element of a list?

For example, if you want to get the second item in a list (with an index based on zero):

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

gives

 "c" 
+1
source

Cat-skinning is fun. Here is a low level approach.

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

This is Lispy's answer, I suspect this expert in Clojure might do it better:

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

It seems you want to use the nth function.

From the docs for this feature:

 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. 

This last sentence means that, in practice, nth is slower for “farther” elements in the sequence, without guaranteeing faster work for collections that, in principle, support faster access (~ O (n)) to indexed elements. For sequences (clojure) this makes sense; The clojure seq API is based on the linked list API and in the linked list, you can only access the nth element by going through each element in front of it. Keeping this constraint is what makes specific list implementations interchangeable with lazy sequences.

Clojure collection access functions are usually designed this way; functions that have significantly better access times to specific collections have separate names and cannot be used “accidentally” in slower collections.

As an example of a collection type that supports fast random access to items, clojure vectors can be called; (index-index of a vector collection) gives an element in the index index number - and note that clojure seqs are not callable.

0
source

Source: https://habr.com/ru/post/1380662/


All Articles