首页 > 解决方案 > 如何打破 Clojure 中的 for 循环?

问题描述

我有以下功能:

(defn next-transformation
  [arr]
  (let [
        arr-len (count arr)
        i-range (range 0 arr-len)
        j-range (range 0 arr-len)
        indexes (for [i i-range
                      j j-range]
              (let [
                   xi (nth arr i)
                   xj (nth arr j)
                   ]
                (if (> xi xj)
                  [i j] 
                  nil
                  )
               )
            ) 
        non-nil-indexes (filter
                         (fn [elem]
                           (not (= elem nil))
                           )
                         indexes 
                        ) 
        ]
    (if (not (empty? non-nil-indexes))
       (first non-nil-indexes)
       nil
      )
    )
)

它返回元组数组的第一个元素,元组[i j]描述数组arrarr[i] > arr[j]为真的元素。

下面for片段中的循环遍历每一对 i 和 j:

indexes (for [i i-range
              j j-range]
      (let [
           xi (nth arr i)
           xj (nth arr j)
           ]
        (if (> xi xj)
          [i j] ;; I want the loop to stop here
          nil
          )
       )
    ) 

如何修改这个 for 循环,使其在找到第一个相关元组后停止(即循环应该在标有;; I want the loop to stop here注释的地方停止)?

这是Java中的等效代码:

private Integer[] next-transformation(final Integer[] arr) {
  for (int i=0; i < arr.length; i++) {
     for (int j=0; j < arr.length; j++) {
       if (arr[i] > arr[j]) {
         return new Integer[] {i, j};
       }
     }
  }

}

更新1:

正如@CharlesDuffy 推荐的那样,我forloop/替换了recur

(defn next-transformation
  [arr]
  (loop [i 0
         j 0]
    (let [
          arr-len (count arr)
          ]
      (if (and (< i arr-len)
               (< j arr-len))
        (let [
                xi (nth arr i)
                xj (nth arr j)
                j-plus-1 (+ j 1)
                i-plus-1 (+ i 1)
                new-i (if (< j-plus-1 arr-len)
                       i
                       (+ i 1))
                new-j (if (< j-plus-1 arr-len)
                       (+ j 1)
                       0)
              ]
          (if (> xi xj)
              ;; We found it
              [i j] 
              ;; We haven't found it, recur 
              (recur new-i new-j)
            )
          )
          nil ; We are at the end of the  loop
        ) ; if 
      )
    ) ; loop 
  ) ; defn

标签: clojure

解决方案


for列表推导中,用于:when过滤感兴趣的元组,并用于first仅返回第一个:

(defn next-transformation [arr]
  (first (for [i (range (count arr))
               j (range (count arr))
               :when (> (nth arr i) (nth arr j))]
           [i j])))

推荐阅读