代码之家  ›  专栏  ›  技术社区  ›  Tyler

写这篇文章最惯用的方法是什么?

  •  12
  • Tyler  · 技术社区  · 16 年前

    我编写了一个函数来实现这一点(显示比解释更容易):

    (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)))
          '()))
    

    我知道在Clojure中,列表并不是唯一的一类数据结构。写这个数据结构不可知有意义吗?不管怎样,我的实现是最有效的吗?如果不是,我将如何使它更有效和/或更惯用?

    4 回复  |  直到 16 年前
        1
  •  21
  •   Hamza Yerlikaya    16 年前

    你可以使用内置的配分函数,

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

    
    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.
    
    
        2
  •  5
  •   Jürgen Hötzel    16 年前

    无需编写自己的实现。Clojure提供 隔板 懒惰的 列表 ,如果仅使用数字文字:

     (partition 2 '(1 2 3 4 5 6)) 
    
        3
  •  5
  •   bonobo    16 年前

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

      (defn split [n xs]
         (lazy-seq
             (let [m (take n xs)]
               (if (= n (count m))
                 (cons m (split n (rest xs)))))))
    

    (与您的条件不同的原因,如果(>(count xs)(dec n))'是因为从xs中计算M个元素比每次都计算整个xs集合更有效(这有点像懒惰,因为我们不想遍历整个集合)

    想象一下,每一次迭代都要计算这个巨大范围内的元素会是什么样子:)

      (take 10 (split 2 (range 100000000000)))
    
        => ((0 1) (1 2) (2 3)...)
    
        4
  •  2
  •   j-g-faustus    16 年前

    我已经使用Clojure大约一个月了,所以我可能没有资格指定最惯用的方法;)

    partition 如前所述)。

    这个实现已经相当不确定数据结构了——因为它使用 sequence 操作,它与所有标准数据结构一起工作:

    (split 2 [1 2 3 4 5 6])
    => ((1 2) (2 3) (3 4) (4 5) (5 6))
    
    (split 2 #{1 2 3 4 5 6})
    => ((1 2) (2 3) (3 4) (4 5) (5 6))
    
    (split 2 {1 :a 2 :b 3 :c 4 :d})
    => (([1 :a] [2 :b]) ([2 :b] [3 :c]) ([3 :c] [4 :d]))
    
    (split 2 "abcd")
    => ((\a \b) (\b \c) (\c \d))
    

    使用纯递归的主要限制是受堆栈大小的限制:

    (split 2 (range 10000))
    => java.lang.StackOverflowError
    

    (defn split-loop [n coll]
      (loop [elms coll res [] ]
        (if (< (count elms) n)
          res
          (recur (next elms) (conj res (take n elms))))))
    
    推荐文章