如何在Clojure中对已排序整数数组进行连续分区?
如何在Clojure中实现已排序整数数组的连续分区?
需求是将已排序的整数数组划分为连续递增的分区,例如把[1,2,3,8,9,10,99]拆分为[[1, 2, 3], [8, 9, 10], [99]]。
Ruby实现示例
[1,2,3,8,9,10,99].slice_when { |x, y| y > x + 1 }.to_a
输出结果:
[[1, 2, 3], [8, 9, 10], [99]]
Clojure实现方案
方法一:利用partition-by结合索引差值
partition-by虽然只接受单参数函数,但可以借助连续整数的数学特性实现分组:连续递增的整数,元素值 - 其索引的结果是固定值,非连续位置的差值会发生变化,以此作为分组依据:
(defn split-consecutive [coll] (->> coll (map-indexed vector) (partition-by (fn [[idx num]] (- num idx))) (map #(map second %)))) ;; 调用示例 (split-consecutive [1 2 3 8 9 10 99]) ;; 输出:((1 2 3) (8 9 10) (99))
方法二:用reduce手动模拟分区逻辑
如果更贴近Rubyslice_when的判断逻辑,可以通过reduce遍历数组,直接判断当前元素是否与上一个分区的末尾元素连续:
(defn split-consecutive [coll] (reduce (fn [acc num] (let [last-group (last acc)] (if (and last-group (= (last last-group) (dec num))) (conj (vec (drop-last acc)) (conj last-group num)) (conj acc [num])))) [] coll)) ;; 调用示例 (split-consecutive [1 2 3 8 9 10 99]) ;; 输出:[[1 2 3] [8 9 10] [99]]
方法一代码简洁,依赖数学特性实现;方法二逻辑直观,直接复刻相邻元素的连续性判断逻辑。
内容的提问来源于stack exchange,提问作者Justin Tanner
相关产品推荐
相关产品推荐

