在clojure

时间:2016-03-24 03:55:00

标签: clojure

我正在尝试找到一种在clojure中实现分区(带[]填充)的方法。我认为使用循环并重复并将其映射到列表中是可行的:

 (defn collect-h [v n]
   (loop [i n
          res []
          lst v
          ]
     (if (= 0 i)
       res
       (recur (dec i) (cons (first lst) res) (next lst))
       )
     )
   )

所以问题是实现只适用于第一系列答案“(collect-h [1 2 3 4 5 6 7 8 9 10] 3)会给((1 2 3))”。所以我需要将它映射到整个集合并删除每个循环中的第一个n数字,但这看起来并不高效。我想知道是否有更好的方法来解决它。

修改

所以它应该像这样工作:

(collect-h [1 2 3 4 5 6 7 8 9 10] 3)                   ;; ((1 2 3) (4 5 6) (7 8 9) (10))

相同
(partition 3 3 [] [1 2 3 4 5 6 7 8 9 10])

3 个答案:

答案 0 :(得分:5)

@Timothy-Pratley答案很好,但它不是尾递归,这意味着它会在大量收集的情况下导致堆栈溢出。这是非堆栈消费变体:

(defn my-partition [n items]
  (loop [res [] items items]
    (if (empty? items)
      res
      (recur (conj res (take n items))
             (drop n items)))))

user> (my-partition 3 (range 10))
[(0 1 2) (3 4 5) (6 7 8) (9)]

答案 1 :(得分:3)

建立@ Timothy-Pratley和Clojure源代码,你也可以使用lazy-seq:

(defn partition-ghetto [n xs]
  (lazy-seq (when-let [s (seq xs)]
              (cons (take n s) (partition-ghetto n (drop n s))))))

答案 2 :(得分:2)

这个怎么样?

(defn partition-ghetto [n xs]
  (if (seq xs)
    (cons (take n xs) (partition-ghetto n (drop n xs)))
    ()))

(partition-ghetto 3 (range 10))
=> ((0 1 2) (3 4 5) (6 7 8) (9))

绝对不如核心版本好,但可能提供一些想法?

请注意,这个递归定义不是尾递归的,所以会为大序列吹掉堆栈,也不像大多数Clojure序列函数那样懒惰。懒惰对序列的优点是在流上操作时既不是堆栈也不是堆绑定。请参阅下面的替代答案,为这些问题提供解决方案。