如何在Clojure中找到向量中最小成员的索引?

8

我曾使用下面这个表达式来获取向量中最小数字的索引。然而,出于效率和数字精度的考虑,我想避免使用.indexOf(尽管我猜测数字会被隐式转换为字符串)。

(.indexOf [1 2 3 4 0 5]
  (reduce #(if (< %1 %2) %1 %2) [1 2 3 4 0 5] ))

使用reduce是否可以以不同的方式完成它?

4个回答

18
用户=> (第一个 (应用最小键值 函数 第二个 (映射索引化的向量 [1 2 4 0 5])))
3

可以通过使用http://clojuredocs.org/clojure_contrib/clojure.contrib.seq-utils/indexed来稍微简化。 - opqdonut
请注意,我认为上面的评论不再正确 - 在Clojure 1.3中似乎不存在“indexed”函数。 - zeptonaut

6
我建议使用循环/递归来高效地完成此任务,可能类似于以下内容:
(defn min-index [v] 
  (let [length (count v)]
    (loop [minimum (v 0)
           min-index 0
           i 1]
      (if (< i length)
        (let [value (v i)]
          (if (< value minimum)
            (recur value i (inc i))
            (recur minimum min-index (inc i))))
        min-index))))

这个想法是迭代整个向量,在每个点上跟踪最小值和迄今为止找到的最小值的索引。


你选择不使其能够处理空输入的原因是什么?只是为了简洁吗? - Eric Auld

2

您也可以使用 reduce

(def v [1 2 3 4 0 5])

(second (reduce (fn [[curr-min min-idx curr-idx] val]
  (if (< val curr-min)
    [val curr-idx (inc curr-idx)]
    [curr-min min-idx (inc curr-idx)])) [(first v) 0 0] v)) ;; => 4
< p > reduce 的结果实际上是一个三元向量,包括最小值、它的索引和一个索引跟踪器(不重要),并且它只遍历集合一次。

reduce 提供的初始值基本上是集合的第一个元素。

我知道这个问题很旧,但它在这里是为了纪念。


1

接下来是@Alex Taggart的回答,使用thread-last宏

user=> (->> [1 2 4 0 5]
  (map-indexed vector)   ; [[0 1] [1 2] [2 4] [3 0] [4 5]]
  (apply min-key second) ; [3 0]
  first)
3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接