通过执行状态减少clojure集合
我正在学习clojure(来自ruby),在思考生成集合的最佳方法时遇到了一些困难 我想写一个函数,它接受两个参数——向量通过执行状态减少clojure集合,clojure,Clojure,我正在学习clojure(来自ruby),在思考生成集合的最佳方法时遇到了一些困难 我想写一个函数,它接受两个参数——向量ary和整数sum——并生成一个新的2D向量,其中每一行的和是(defn在sum[ary sum]之后分割) (让[acc v](减少[fn[[acc v s]x] (让[new-s(+sx)] (如果(如Michał所示,则累积状态a可以在元组中与相关元素连接 下面是一种命令式方法,其中状态保存在循环绑定中 (defn split-after-sum [ary sum]
ary
和整数sum
——并生成一个新的2D向量,其中每一行的和是(defn在sum[ary sum]之后分割)
(让[acc v](减少[fn[[acc v s]x]
(让[new-s(+sx)]
(如果(如Michał所示,则累积状态a可以在元组中与相关元素连接
下面是一种命令式方法,其中状态保存在循环绑定中
(defn split-after-sum [ary sum]
(when (seq ary)
(loop [ary ary
cur 0
row []
rows []]
(if-let [[x & xs] ary]
(let [nxt (+ x cur)]
(if (<= nxt sum)
(recur xs nxt (conj row x) rows)
(recur xs x [x] (conj rows row))))
(conj rows row)))))
(求和后的定义拆分[三元和]
(时间(续)
(循环
cur0
第[]行
行[]]
(如果让[[x&xs]ary]
(设[nxt(+x cur)]
(如果这与我的方法很相似——使用减少,通过多个参数保持状态以减少。你认为这很好吗?clojure?是的,它非常好clojure。它也非常快:特别是,它比循环
/重复
方法快。减少
是clojure中的一个核心概念,它的性能特征已经并将继续受到广泛关注。(我用于基准测试。在这里,我对上述答案示例中使用的小向量以及由(shuffle(range len))
生成的两个向量进行了基准测试,一个长度为1024,另一个长度为16384;sum的值分别为7、17和173。)太棒了,谢谢你对它进行基准测试。我不太担心速度,更担心学习正确的方法来解决问题,但这对我来说是一个很好的迹象,我直觉上做的事情实际上非常快。你会推荐这种方法而不是函数式方法吗?我不会称之为命令式方法——相反,它是通过递归循环的,这是函数式,如果不如使用标准组合器那样声明性(循环局部变量在下一次迭代中并行反弹)。有关一些基准测试结果,请参阅我对spike对我答案的评论的回应。我完全同意参数顺序。
(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]
(split-after-sum [1 1 1 1 1 1 1 1 1] 2) => [[1 1] [1 1] [1 1] [1 1] [1]]
(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]]
(defn split-after-sum [ary sum]
(when (seq ary)
(loop [ary ary
cur 0
row []
rows []]
(if-let [[x & xs] ary]
(let [nxt (+ x cur)]
(if (<= nxt sum)
(recur xs nxt (conj row x) rows)
(recur xs x [x] (conj rows row))))
(conj rows row)))))