您的代码的意图似乎与您在评论中的描述不同,所以我并不完全相信我理解。也就是说,loop
/recur
绝对是解决问题的有效方法。
这是我想出的:
(defn get-cycle [xs]
(loop [xs xs index 0]
(when-let [[x & more] (seq xs)]
(when-let [[y] (seq more)]
(if (= x y)
{x [index (inc index)]}
(recur more (inc index)))))))
这会将重复项目的映射返回到该项目所在的两个索引的向量。
(get-cycle [1 1 2 1 2 4 2 1 4 5 6 7])
;=> {1 [0 1]}
(get-cycle [1 2 1 2 4 2 1 4 5 6 7 7])
;=> {7 [10 11]}
(get-cycle [1 2 1 2 4 2 1 4 5 6 7 8])
;=> nil
这是使用序列函数的替代解决方案。我更喜欢这种方式,但它是否更短或更优雅可能是主观的。
(defn pairwise [coll]
(map vector coll (rest coll)))
(defn find-first [pred xs]
(first (filter pred xs)))
(defn get-cycle [xs]
(find-first #(apply = (val (first %)))
(map-indexed hash-map (pairwise xs))))
根据@demi 的说明进行编辑
啊,明白了。这是你的想法吗?
(defn get-cycle [xs]
(loop [xs (map-indexed vector xs)]
(when-let [[[i n] & more] (seq xs)]
(if-let [[j _] (find-first #(= n (second %)) more)]
{n [i j]}
(recur more)))))
我重用find-first
了我之前基于序列的解决方案。