在ClojureScript中移动范围?

时间:2016-09-29 16:21:04

标签: range clojurescript

如何在ClojureScript中移动范围?

例如,让我们说我们有范围:

(range 3)

给出:(0 1 2)

我正在寻找一个将值向左移动的函数:(1 2 0)或类似(2 0 1)

我想出了一个我将分享的实现作为答案。我想应该是一些内置函数来做到这一点?但我没有找到任何东西。

4 个答案:

答案 0 :(得分:2)

这是我写的函数:

(defn <-range [n l]
  (concat (drop n (range l)) (range n)))

简要说明:

  • (range l)创建一个长度为l
  • 的范围
  • (drop n)删除n个元素
  • (range n)创建一个新范围,直到n
  • (concat)连接两个范围

如果我尝试:

  • (<-range 0 4)提供(0 1 2 3)
  • (<-range 2 4)提供(2 3 0 1)
  • (<-range 4 4)提供(0 1 2 3)

答案 1 :(得分:1)

我已经颠倒了你的args的顺序,因为这更接近于range args的工作方式。 lazy-cat可能优于concat,因为它甚至无法评估第二个range,直到需要它为止。

(defn <-range [length start-index]
  (lazy-cat (range start-index length)
            (range start-index)))

答案 2 :(得分:1)

还有一个cycle函数,(不出所料)循环一个集合(以避免连接):

user> (defn <-range [n l]
        (->> (range l)
             cycle
             (drop n)
             (take l)))
#'user/<-range

user> (<-range 0 4)
(0 1 2 3)

user> (<-range 2 4)
(2 3 0 1)

user> (<-range 4 4)
(0 1 2 3)

根据余下的内容,即使没有调用range,你也可以这样做:

user> (defn <-range [n l]
        (take l (iterate #(rem (inc %) l) (rem n l))))

或者像这样:

user> (defn <-range [n l]
        (map #(rem (+ % n) l) (range l)))

答案 3 :(得分:1)

我认为range仅用作示例,您真的希望能够对任何集合执行此操作。

(defn rotate-left [c]
  (lazy-cat (drop 1 c) (take 1 c)))

或能够选择性地指定多于1次旋转,

(defn rotate-left
  ([c] (rot-left 1 c))
  ([n c] (lazy-cat (drop n c) (take n c))))

使用这个, (rotate-left (range 3))会产生(1, 2, 0)(rotate-left 2 (range 3))会产生(2, 0, 1)