私はベクトルx
とy
ユニークなアイテムのペアを持っており、それぞれがソートされていることがわかっています。ソート順を維持しながら、2つの交差点が欲しいです。結果は、高速ランダムアクセスのための別のベクトルになるのが理想的です。
以下の世代は、単なる例のためであり、x
事前y
に分類され、事前に区別されます(実際には時間サンプルです)。
(defn gen-example [c] (-> (repeatedly c #(-> c rand int)) distinct sort vec))
user=> (def x (gen-example 100000)) (count x)
#'user/x
63161
user=> (def y (gen-example 100000)) (count y)
#'user/y
63224
私はClojureがclojure.set/intersection
で動作することができることを知っていますsorted-set
。私x
とy
は同じプロパティ(ソートされた個別の要素)を持っていますが、同じタイプではありません。
質問1:すでに区別されてソートされている場合よりもx
、sに変換y
するためのより良い/より速い方法はありますか?sorted-set
(apply sorted-set x)
user=> (time (def ssx (apply sorted-set x)))
"Elapsed time: 607.642592 msecs"
user=> (time (def ssy (apply sorted-set y)))
"Elapsed time: 617.046022 msecs"
これで交差点を実行する準備ができました
user=> (time (count (clojure.set/intersection ssx ssy)))
"Elapsed time: 355.42534 msecs"
39992
これはやや期待外れのパフォーマンスであり、ざっと見てみると、(source clojure.set/intersection)
これらのセットがソートされているという事実に対する特別な扱いは示されていないようです。
質問2:sorted-set
sの共通部分を実行するためのより良い/より速い方法はありclojure.set/intersection
ますか?
(defn intersect-sorted-vector [x y]
(loop [x (seq x) y (seq y) acc []]
(if (and x y)
(let [x1 (first x)
y1 (first y)]
(cond
( < x1 y1) (recur (next x) y acc)
( > x1 y1) (recur x (next y) acc)
:else (recur (next x) (next y) (conj acc x1))))
acc)))
これはかなり(ほぼ10倍)高速であることがわかります。
user=> (time (count (intersect-sorted-vector x y)))
"Elapsed time: 40.142532 msecs"
39992
しかし、私のコードが過度に手続き的/反復的であると感じずにはいられません。
質問3:Clojureでベクトルのペアを処理するためのより慣用的な方法を誰かが親切に提案できますか?