どうすれば ClojureScriptで範囲をシフトできますか?例えばClojureScriptで範囲を移動しますか?
は、我々は範囲を持っているとしましょう:
(range 3)
与える:(0 1 2)
を、私はこのように左に値をシフトする機能を探しています:(1 2 0)
またはこのよう(2 0 1)
私は答えとして共有する実装を考え出しました。私はこれを行うための組み込み関数がいくつかあるはずですか?しかし、私は何も見つけられませんでした。
どうすれば ClojureScriptで範囲をシフトできますか?例えばClojureScriptで範囲を移動しますか?
は、我々は範囲を持っているとしましょう:
(range 3)
与える:(0 1 2)
を、私はこのように左に値をシフトする機能を探しています:(1 2 0)
またはこのよう(2 0 1)
私は答えとして共有する実装を考え出しました。私はこれを行うための組み込み関数がいくつかあるはずですか?しかし、私は何も見つけられませんでした。
これは私が書いた関数である:
(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)
を与えていますargs、これはどのように近い感じですrange
は仕事をargsします。 lazy-cat
はおそらくconcat
よりも好ましいでしょう。それは、それが必要になるまで第2のrange
を評価しないからです。
(defn <-range [length start-index]
(lazy-cat (range start-index length)
(range start-index)))
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)))
私も 'cycle'を使いたかったのですが、アルゴリズムがうまくいかなかったのです! LightTableを使って少しテストベンチを作って、 '5000'でシフトされた '1000000'の範囲で見つけました。私はあなたの関数が 'concat'や' lazy-cat'を使うよりも速いと思っていましたが、200msから300ms遅いようです。これは私を驚かせました...代わりに、 'concat'や' lazy-cat'はクロムの2800-3000ms前後のタイミングがほとんどです。 – Marcs
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)
ニースを指定任意する能力を有します。 * lazyness *は、 'take 'のような関数が' <-range'の前に呼び出される場合、または' take 'を使わない場合にのみ機能します。 – Marcs
ええ、それはすべての標準的な怠惰のルールに従います。 –