0

この疑似 C++ コードのようなことを行うにはどうすればよいですか。

vector<int> vs = {...};
for (i = start; i < vs.size(); i += step) {
  vs[i] *= 10;
}

クロジュアで?私はこのコードを持っています:

(defn step-do [start step v]
  (if (< start (count v))
    (recur (+ start step) step (assoc v start (* 10 (v start))))
    v))

(defn -main
  [& args]
  (println (step-do 2 3 (vec (range 1 15)))))

またはforバリアント:

(defn step-do [start step v]
  (last (for [i (range start (count v) step)]
          (assoc v i (* 10 (v i))))))

何が良いですか?何が速いですか?私は何か他のことをすべきですか?

4

2 に答える 2

2

ベースのrecurバージョンは完全に問題なく、可能な限り最速のソリューションの 1 つになる可能性がありますが、より大きなベクトルで動作する場合はトランジェントを使用することをお勧めします。

reduce可能な代替手段として、アキュムレータの初期値として渡された入力ベクトルとrangeステップ引数で提供される削減されたシーケンスを使用して、ループを処理するために使用することをお勧めします。

(defn step-do [start step v]
  (reduce (fn [v i]
            (assoc v i (* 10 (nth v i))))
          v
          (range start (count v) step)))

REPL から:

(def xs (vec (range 32)))

(step-do 1 2 xs)
;= [0 10 2 30 4 50 6 70 8 90 10 110 12 130 14 150 16 170 18 190 20 210 22 230 24 250 26 270 28 290 30 310]

これには、変換が適用されるインデックスの選択 (ここでは によって処理されrangeます。必要に応じて、より複雑な seq プロデューサーを使用できます) と変換自体 ( に渡される関数によってキャプチャされreduceます。一般化されたstep-do可能性があります) を明確に分離するという利点があります。ハードウェアの 10 倍の乗算ではなく、変換関数を引数として受け入れます)。

さらに、これは非常にパフォーマンスが高いはずです (そして、reduceClojure のデータ処理モデルの中心であるため、将来のリリースで改善され続ける可能性があります)。もちろん、ここでもトランジェントを使用して速度を上げることができます。

于 2013-07-24T01:28:30.030 に答える