回收提前终止上的迭代

时间:2019-04-18 13:29:05

标签: clojure

我有一个匿名函数,带有一个以持久性数组map作为参数(还有一个用于累积结果的map)的reduce。因此,在缩减期间,lambda函数将在所有键/值对上进行迭代。但是我需要根据条件停止整个还原过程。问题在于,“减少”仅针对当前键终止,并不能阻止继续进行后续操作,并且结果会像我没有满足条件那样被累积!

(defn my-func [my-map src]
  (reduce (fn [acc [k v]] ; on cond I want to stop look on [k v] pairs and exit reuction and even my-func !!! 
    (assoc acc (key value))) (empty src) my-map))

我期望的是一种尽早终止的方法,例如说一个空值。

2 个答案:

答案 0 :(得分:2)

减少了“作品”:

(reduce #(if (< %2 100) %2 (reduced :one-hundred)) (range 1 100))
99
(reduce #(if (< %2 100) %2 (reduced :one-hundred)) (range 1 101))
:one-hundred

但是,地图或集合的迭代顺序可能不是您期望的:

(reduce #(if (< %2 1000) (inc %1) (reduced %1)) 0 (apply hash-set (range 1000)))
1000
(reduce #(if (< %2 999) (inc %1) (reduced %1)) 0 (apply hash-set (range 1000)))
510
(reduce #(if (< %2 998) (inc %1) (reduced %1)) 0 (apply hash-set (range 1000)))
157

通过一些简化尝试匹配您拥有的表单。此版本将复制输入映射,除非键:a缩小为空映射时不存在。

(defn my-func [m]
  (reduce (fn [acc [k v]]
            (if (= k :a) (reduced {}) ;; if cond return empty
                (assoc acc k v))) {} m))
(my-func {:b 4 :c 7})
;; =>
{:b 4, :c 7}

(my-func {:a 2 :d 6})
;; =>
{}

答案 1 :(得分:0)

如果我正确理解您的问题:如果您的地图具有满足条件的键和/或值,则您不希望处理该地图,而只是返回一些您早已退出的标记。您可以为此使用循环:

(defn my-func [my-map]
  (loop [m my-map]
    (if-let [[k v] (first m)]
      (if (= v 4) ;; your condition for exit-early
        :four     ;; return your exit-early marker
        (recur (rest m)))
      my-map))) ;; you looped throught the whole map without exit-early
(my-func {:a 1 :b 2 :c 3 :d 4 :e 5})

您甚至可以传入exit-early-predicate和一个标记作为参数:

(defn my-func [my-map kv-exit-pred marker]
  (loop [m my-map]
    (if-let [[k v] (first m)]
      (if (kv-exit-pred k v) 
        marker     
        (recur (rest m)))
      my-map))) 
(my-func {:a 1 :b 2 :c 3 :d 4 :e 5} #(= %2 3) :three)

在这两种情况下,如果您不提早退房,那么只需返回原始地图即可(因为这是您的reduce函数在实践中所做的事情)。