写这篇文章最恰当的Clojure方式是什么?

Tyl*_*ler 12 idioms clojure

我写了这个函数来做这个(比说明更容易显示):

(split 2 (list 1 2 3 4 5 6))

=> ((1 2) (2 3) (3 4) (4 5) (5 6))

(defn split [n xs] 
  (if (> (count xs) (dec n))
      (cons (take n xs) (split n (rest xs)))
      '()))
Run Code Online (Sandbox Code Playgroud)

据我所知,在Clojure中,列表并不是唯一的第一类数据结构.编写这种数据结构不可知是否有意义?无论如何,我的实施是最有效的,如果不是,我将如何使其更有效和/或惯用?

谢谢!

Ham*_*aya 21

你可以使用内置的分区功能,

(partition 2 1 (list 1 2 3 4 5 6))
=> ((1 2) (2 3) (3 4) (4 5) (5 6))
Run Code Online (Sandbox Code Playgroud)

适用于任何序列.


clojure.core/partition
([n coll] [n step coll] [n step pad coll])
  Returns a lazy sequence of lists of n items each, at offsets step
  apart. If step is not supplied, defaults to n, i.e. the partitions
  do not overlap. If a pad collection is supplied, use its elements as
  necessary to complete last partition upto n items. In case there are
  not enough padding elements, return a partition with less than n items.


Jür*_*zel 5

无需编写自己的实现.Clojure中提供的分区,这是.如果你只使用数字文字,也不需要使用列表:

 (partition 2 '(1 2 3 4 5 6)) 
Run Code Online (Sandbox Code Playgroud)


bon*_*obo 5

您可以从您的版本中创建一个延迟序列:

  (defn split [n xs]
     (lazy-seq
         (let [m (take n xs)]
           (if (= n (count m))
             (cons m (split n (rest xs)))))))
Run Code Online (Sandbox Code Playgroud)

(条件与你的'(if(>(count xs)(dec n))'不同的原因是因为它更有效地计算XS中的M个元素而不是每次都计算整个XS集合(这是一种反对懒惰,因为我们不想走整个集合)

想象一下,每次迭代计算怪异范围内的元素会是什么样的:)

  (take 10 (split 2 (range 100000000000)))

    => ((0 1) (1 2) (2 3)...)
Run Code Online (Sandbox Code Playgroud)