Clojure:列表或其他集合中值的索引

时间:2011-11-10 22:15:46

标签: clojure

如何获取字符串列表中任何元素的索引:

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

例如,(function "a")必须返回0,(function "b") 1,(function "c") 2,依此类推。

和...如果处理很长的数据列表,使用任何其他类型的集合会更好吗?

8 个答案:

答案 0 :(得分:7)

我不确定我理解你的问题。你想要列表中每个字符串的第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将返回第一个索引,而index-map将返回 last < / em>的

答案 1 :(得分:7)

Christian Berg的答案很好。也可以回到Java的indexOfString方法:

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

=&GT; 2

当然,这只适用于字符串(长度为1)或字符的列表(或更一般的,seqs)。

更通用的方法是:

(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

答案 2 :(得分:3)

您可以将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)))

答案 3 :(得分:1)

您的意思是,如何获得列表的第n个元素?

例如,如果要获取列表中的第二个元素(使用从零开始的索引):

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

产量

"c"

答案 4 :(得分:1)

猫皮很有趣。这是一种低级方法。

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

答案 5 :(得分:1)

这是一个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)))

答案 6 :(得分:0)

您似乎想要使用第n个函数。

来自该职能部门的文件:

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))的集合更快地工作。对于(clojure)序列,这是有道理的; clojure seq API基于链表API,在链表中,您只能通过遍历其前的每个项目来访问第n个项目。保持这种限制是使具体列表实现与惰性序列互换的原因。

Clojure集合访问功能通常以这种方式设计;在特定集合上具有明显更好的访问时间的函数具有单独的名称,并且不能在较慢的集合上“偶然”使用。

作为支持对项目进行快速“随机”访问的集合类型的示例,可以调用clojure向量; (vector-collection index-number)在索引index-number处产生项目 - 并注意clojure seqs不可调用。

答案 7 :(得分:0)

我知道这个问题已经被回答了一百万次了,但这是一个利用解构的递归解决方案。

(defn index-of-coll
  ([coll elm]
   (index-of-coll coll elm 0))
  ([[first & rest :as coll] elm idx]
   (cond (empty? coll) -1
         (= first elm) idx
         :else (recur rest elm (inc idx)))))