Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过执行状态减少clojure集合_Clojure - Fatal编程技术网

通过执行状态减少clojure集合

通过执行状态减少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]

我正在学习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]
  (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)))))