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

13,296

Solution 1

Christian Berg's answer is fine. Also it is possible to just fall back on Java's indexOf method of class String:

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

; => 2

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

A more general approach would be:

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

More idiomatic would be to lazily 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

Solution 2

I'm not sure I understand your question. Do you want the nth letter of each of the strings in a list? That could be accomplished like this:

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

The result is:

(\b \e \h)

Update

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

One possibility is to search for the string from the beginning of the list and count all the entries you have to 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 have to do a lot of look-ups, it might be more efficient to construct a hash-map of all strings 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, while index-map will return the last.

Solution 3

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

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

Solution 4

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

For example, if you want to get the 2nd element on the list (with zero-based index):

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

yields

"c"

Solution 5

This is a Lispy answer, I suspect those expert in Clojure could 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)))
Share:
13,296
logigolf
Author by

logigolf

Updated on June 04, 2022

Comments

  • logigolf
    logigolf almost 2 years

    How do I get the index of any of the elements on a list of strings as so:

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

    For example, (function "a") would have to return 0, (function "b") 1, (function "c") 2 and so on.

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