16

ベクトル内のすべてのペアの最初の要素をインクリメントする次のコードがあります。

(vec (map (fn [[key value]] [(inc key) value]) [[0 :a] [1 :b]]))

ただし、最初にマップを使用してシーケンスを作成し、次にそれをベクトルにキャストするため、このコードは洗練されていないのではないかと心配しています。

この類似物を考えてみましょう:

(into [] (map (fn [[key value]] [(inc key) value]) [[0 :a] [1 :b]]))

#clojure@irc.freenode.net で、上記のコードを使用するのは良くないと言わinto(reduce conj [] (map-indexed ...))ました。それから、実際にintoは拡張されず(reduce conj ...)、可能な場合はトランジェントを使用すると言われました。また、経過時間を測定するintoと、実際には よりも速いことが示されましたvec

だから私の質問は:

  1. mapベクターを使用する適切な方法は何ですか?
  2. ベクターを使用するvecと、その下で何が起こりますか?into

関連するが重複していない質問:

4

1 に答える 1

31

実際、Clojure 1.4.0 の時点で、これを行うための推奨される方法は を使用することです。これは、戻り値がベクトルであること以外mapvは似ています。mapこれは、不要な中間割り当てがまったくない、断然最も効率的なアプローチです。

Clojure 1.5.0はmap、. _ 1.5.0 アルファ版と、ClojureScript の最近のタグ付きリリースで試すことができます。filtertakedropinto []

(vec some-seq)とに関して(into [] some-seq)は、最初のものは最終的にsome-seq空の一時的なベクトルに注ぐ Java ループに委任されますが、2 番目のものは非常に効率的な Clojure コードで同じことを行います。どちらの場合も、最終的な戻り値を構築するときにどのアプローチを取るかを決定するために、いくつかの初期チェックが必要です。

vec長さinto []が短い (最大 32) Java 配列の場合は大きく異なります。最初は配列にエイリアスを設定し (新しく作成されたベクトルの末尾として使用します)、配列の内容が変更されないように、配列を後で変更しないように要求します。ベクトルの変更 (docstring を参照); 後者は、新しいテールを持つ新しいベクトルを作成し、配列への将来の変更を気にしません。

于 2012-08-20T20:17:58.447 に答える