【问题标题】:select first item of a collection that satisfies given predicate in clojure选择满足clojure中给定谓词的集合的第一项
【发布时间】:2013-12-04 15:26:18
【问题描述】:

clojure 中是否有一个函数(给定一个谓词和一个集合), 选择满足给定谓词的第一项并停止迭代?

例如:

(select-first #(> % 10) (range))
=> 11

如果没有,也许有人可以提示我一个惯用的实现

【问题讨论】:

    标签: clojure


    【解决方案1】:

    有多种可能性。

    some

    some 返回其谓词返回的第一个非零值。

    (some #(when (> % 10) %) (range)) ;; => 11
    

    filter + first

    filter 保留与谓词匹配的那些元素,first 检索其中的第一个。

    (first (filter #(> % 10) (range))) ;; => 11
    

    remove + first

    如果您想找到第一个与您的谓词匹配的元素,remove 是您的朋友:

    (first (remove #(<= % 10) (range))) ;; => 11
    

    或者some:

    (some #(when-not (<= % 10) %) (range)) ;; => 11
    

    所以,我猜就是这样。

    【讨论】:

    • 很高兴我能帮上忙! (虽然另一个答案是在我之前大约 20 秒发布的)
    • 一个警告——(first (filter ...)) 更严格(而且更快,因为过滤器返回一个惰性序列),因为使用some 是模棱两可的——考虑(some #(when (nil? %) %)。使用 some 会找到第一个 non-nil 元素。
    • @djhaskin987 确实,如果您使用some 来查找nil 元素,您将遍历整个序列(因此可能永远不会终止) - 在其他情况下它只会实现尽可能地延迟序列。但是请注意,我对some 的描述已经包含您强调的 non-nil 部分。 :)
    【解决方案2】:

    先使用过滤器

    user=> (->> (range) (filter #(> % 10)) first)
    11
    user=> (first (filter #(> % 10) (range)))
    11
    

    【讨论】:

    • 没有惰性求值不是效率低吗?
    • @JosephGarvin 当然,范围和过滤器是懒惰的。没有惰性求值范围将花费无限时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    • 2012-04-28
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多