2016-09-29 6 views
0

どうすれば ClojureScriptで範囲をシフトできますか?例えばClojureScriptで範囲を移動しますか?

は、我々は範囲を持っているとしましょう:

(range 3) 

与える:(0 1 2)

を、私はこのように左に値をシフトする機能を探しています:(1 2 0)またはこのよう(2 0 1)

私は答えとして共有する実装を考え出しました。私はこれを行うための組み込み関数がいくつかあるはずですか?しかし、私は何も見つけられませんでした。

答えて

2

これは私が書いた関数である:

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

簡単な説明:

  • (range l)
  • (drop n)ドロップn個の要素
  • (range n)新しい範囲を作成する長さLの範囲を作成しますnまで
  • 私がしようとした場合、両方の範囲

10 CONCATは:

  • (<-range 0 4)(0 1 2 3)
  • (<-range 2 4)を与える(2 3 0 1)
  • (<-range 4 4)は、私はあなたの順序を逆にしました(0 1 2 3)
1

を与えていますargs、これはどのように近い感じですrangeは仕事をargsします。 lazy-catはおそらくconcatよりも好ましいでしょう。それは、それが必要になるまで第2のrangeを評価しないからです。

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

ニースを指定任意する能力を有します。 * lazyness *は、 'take 'のような関数が' <-range'の前に呼び出される場合、または' take 'を使わない場合にのみ機能します。 – Marcs

+0

ええ、それはすべての標準的な怠惰のルールに従います。 –

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))) 
+0

私も 'cycle'を使いたかったのですが、アルゴリズムがうまくいかなかったのです! LightTableを使って少しテストベンチを作って、 '5000'でシフトされた '1000000'の範囲で見つけました。私はあなたの関数が 'concat'や' lazy-cat'を使うよりも速いと思っていましたが、200msから300ms遅いようです。これは私を驚かせました...代わりに、 'concat'や' lazy-cat'はクロムの2800-3000ms前後のタイミングがほとんどです。 – Marcs

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)

関連する問題