web-dev-qa-db-ja.com

Clojure:インデックスを使用してベクトル内の各要素の関数を呼び出します

私がベクトルを持っているとしましょう:

(def data ["Hello" "World" "Test" "This"])

そして、APIを含むテーブルをどこかに入力したいと思います。

(defn setCell
  [row col value]
  (some code here))

次に、次の呼び出しを実行するための最良の方法は何ですか。

(setCell 0 0 "Hello")
(setCell 0 1 "World")
(setCell 0 2 "Test")
(setCell 0 3 "This")

私は以下がうまくいくことを発見しました:

(let [idv (map vector (iterate inc 0) data)]
  (doseq [[index value] idv] (setCell 0 index value)))

しかし、新しい一時データ構造idvを必要としないより高速な方法はありますか?

26
Jeroen Dirks

あなたがそれをしている方法は慣用的です(そして実際にはclojure.contrib.seq-utils/indexedと同じです)。余分なデータ構造を本当に避けたい場合は、次のようにすることができます。

(loop [data data, index 0]
  (when (seq data)
    (setCell 0 index (first data))
    (recur (rest data) (inc index))))

正当な理由がない限り、私はあなたのバージョンを使用します。

10
Brian Carper

インデックスをデータと一緒にマッピングするだけで、非常に慣用的な方法で同じ効果を得ることができます。

(map #(setCell 0 %1 %2) (iterate inc 0) data)

これを(doallまたは(doseqでラップして、今すぐ電話をかけることができます。最短のシーケンスがなくなるとマップが停止するため、無限のシーケンスを有限のシーケンスと一緒にマップするのは問題ありません。

27
Arthur Ulfeldt

ゲームの少し遅いですが、このページにアクセスする人のために:clojure.coreで利用可能なmap-indexed関数が(clojure 1.2以降)あります。

1つの問題(私が間違っていない限り):「pmap」に相当するものがないため、マップインデックス付きの計算を簡単に並列化することはできません。その場合は、上記のソリューションを参照します。

27
Rollo Tomazzi

最も良い方法は、clojure.contrib.seq-utils/indexedを使用することです。これは、次のようになります(破棄を使用)。

(doseq [[idx val] (indexed ["Hello" "World" "Test" "This"])]
  (setCell 0 idx val))
8
pmf

オプションソファのパフォーマンスを簡単に比較しました。

; just some function that sums stuff 
(defn testThis
  [i value]
 (def total (+ total i value)))

; our test dataset. Make it non-lazy with doall    
(def testD (doall (range 100000)))

; time using Arthur's suggestion
(def total 0.0)
(time (doall (map #(testThis %1 %2) (iterate inc 0) testD)))
(println "Total: " total)

; time using Brian's recursive version
(def total 0.0)
(time (loop [d testD i 0]
  (when (seq d)
    (testThis i (first d))
    (recur (rest d) (inc i)))))
(println "Total: " total)

; with the idiomatic indexed version
(def total 0.0)
(time (let [idv (map vector (iterate inc 0) testD)]
  (doseq [[i value] idv] (testThis i value))))
(println "Total: " total)

私の1コアラップトップでの結果:

   "Elapsed time: 598.224635 msecs"
   Total:  9.9999E9
   "Elapsed time: 241.573161 msecs"
   Total:  9.9999E9
   "Elapsed time: 959.050662 msecs"
   Total:  9.9999E9

予備的結論:

ループ/繰り返しソリューションを使用します。

1
Jeroen Dirks