【问题标题】:Find index of an element matching a predicate in Clojure?在 Clojure 中查找与谓词匹配的元素的索引?
【发布时间】:2011-12-27 04:54:07
【问题描述】:

使用 Clojure,如何在该向量 [-1 0 3 7 9] 中找到第一个具有正值的索引?

我知道您可以使用firstfilter 相当优雅地获得第一个结果:

(first (filter pos? [-1 0 99 100 101]))

此代码返回值99。我想要的答案是索引是2

【问题讨论】:

标签: clojure


【解决方案1】:

使用keep-indexed,您可以获得满足谓词的索引序列:

(defn indices [pred coll]
   (keep-indexed #(when (pred %2) %1) coll))

通过这个简单的函数,您将解决表达式问题

user=> (first (indices pos? [-1 0 99 100 101]))
2

请注意,由于keep-indexed(和indices)的惰性,不需要实现整个序列,因此不会执行无关的计算。

【讨论】:

  • 这很好用。 (当我深入研究时,我注意到 keep-indexed 包含 non-nil(其中包括 false)结果。我不知道这样做的理由。)
【解决方案2】:
(defn first-pos [x] 
  (loop [arr x n 0]
     (if (pos? (first arr))
     n
     (recur (next arr) (inc n)))))

这是使用函数式编程强大的尾递归的一个很好的例子。

【讨论】:

  • 如果列表中没有正元素,它会失败并返回NullPointerException; OP 还要求匹配任意谓词,而不仅仅是 pos?
【解决方案3】:
(first (filter #(not (nil? %)) (map #(when (pos? %1) %2) [-1 1 0 99 100 101] (range))))

Map可以取一个或多个集合并返回一个列表,在map上放置条件,过滤nil。

【讨论】:

    【解决方案4】:
    (defn pred-idx [pred [idx hist] cur]
      (if (pred cur)
        [(inc idx) (conj hist idx)]
        [(inc idx) hist]))
    
    (defn idx-filter [pred col]
      (second (reduce (partial pred-idx pred) [0 []] col)))
    
    (first (idx-filter pos? [-1 0 99 100 101]))
    2
    

    不确定这是否更好,但它有效。我认为它强制评估整个序列,如果你需要所有索引会更好。正确的做法可能是不知何故把它变成一个懒惰的序列,但我已经完成了晚上的工作。

    【讨论】:

    • 我想要一些可以处理我的例子的东西。查找集合中第一个正值的索引。
    • 我把这个卡在了大脑上,所以一直在尝试。虽然不是理想的解决方案。
    【解决方案5】:

    我参加聚会有点晚了,但我更喜欢:

    (defn index-of-pred
      [pred coll]
      (ffirst (filter (comp pred second) (map-indexed list coll))))
    
    ;; example usage
    (index-of-pred pos? [-1 -2 -5 0 3 4 1 -100])
    ;=> 4
    

    【讨论】:

      【解决方案6】:

      试试这个:

      (defn first-index
        ([pred coll] (first-index coll pred 0))
        ([pred coll idx]
          (cond (= coll '()) -1
                (pred (first coll)) idx
                :else (recur pred (rest coll) (inc idx)))))
      

      并像这样使用它:

      (defn is-pos? [x]
        (> x 0))
      
      (first-index is-pos? [-1 0 3 7 9])
      

      它返回满足谓词的第一个元素的从零开始的索引(示例中为is-pos?),如果没有元素与谓词匹配,则返回-1。

      【讨论】:

      • 此函数仅在显式传递nil 时返回-1,因为(rest x) 对于任何x 都不会为零。在测试它是否为零之前,您应该在集合上调用seq。此外,[pred coll] 将是比[coll pred] 更友好的参数顺序 - 参见。例如mapfilter
      • 这可行(根据 amalloy 的建议),但使用 keep-indexed 的版本要简单得多。
      • 那里,我根据@amalloy 的评论对其进行了编辑。来自 Scheme 背景,Clojure 中的 nil != '() 很奇怪
      猜你喜欢
      • 1970-01-01
      • 2012-01-21
      • 2018-01-24
      • 1970-01-01
      • 2012-03-22
      • 2016-03-06
      • 2018-12-03
      • 2020-04-29
      相关资源
      最近更新 更多