通过状态减少clojure集合

spi*_*ike 4 clojure

我正在学习clojure(来自ruby)并且在围绕生成集合的最佳方式时遇到一些麻烦.

我想写一个带有两个参数的函数 - 向量ary和整数sum- 并生成一个新的2D向量,其中每行的总和<=输入和(忽略输入验证).我遇到麻烦的概念点是如何在建立新集合的同时保持"当前行总和"的状态.

这是我得到的:

(defn split-after-sum [ary sum]
  (reduce (fn [acc i]
            (let [inner-sum (+ (last acc) i)]
              (if (< inner-sum sum)
                [(conj (first acc) i) (+ i (last acc))]
                [(conj (first acc) i "X") 0])))
          [[] 0] ary))
Run Code Online (Sandbox Code Playgroud)

我正在传递reduce一个2元素向量,以便跟踪我正在构建的集合和此行的总计数.

它有点工作.我还没弄明白如何将结果实际制作为2D数组,所以它只是粘贴"X",其中的分割应该是:

(first (split-after-sum [1 1 1 1 1 1 1 1 1] 2)) => [1 1 "X" 1 1 "X" 1 1 "X" 1 1 "X" 1]
Run Code Online (Sandbox Code Playgroud)

理想的输出是:

(split-after-sum [1 1 1 1 1 1 1 1 1] 2) => [[1 1] [1 1] [1 1] [1 1] [1]]
Run Code Online (Sandbox Code Playgroud)

我知道这里有一些混乱的东西,但我认为这个问题的惯用答案是有启发性的.

Mic*_*zyk 7

(defn split-after-sum [ary sum]
  (let [[acc v] (reduce (fn [[acc v s] x]
                          (let [new-s (+ s x)]
                            (if (<= new-s sum)
                              [acc (conj v x) new-s]
                              [(conj acc v) [x] x])))
                        [[] [] 0]
                        ary)]
    (conj acc v)))

(split-after-sum [1 1 3 2 1 1 1 1 1] 3)
;= [[1 1] [3] [2 1] [1 1 1] [1]]
(split-after-sum [1 1 3 2 1 1 1 1 1] 4)
;= [[1 1] [3] [2 1 1] [1 1 1]]
(split-after-sum [1 1 3 2 1 1 1 1 1] 5)
;= [[1 1 3] [2 1 1 1] [1 1]]
(split-after-sum [1 1 3 2 1 1 1 1 1] 6)
;= [[1 1 3] [2 1 1 1 1] [1]]
Run Code Online (Sandbox Code Playgroud)