8

clojure でさまざまなサイズのコレクションを操作する慣用的な方法を理解したいと思います。関数「マップ」に、コレクションの残りの部分にデフォルト値を埋め込むように指示する方法はありますか?

例として、3 つのベクトルがあるとします。

(def x [1 2 3 4])
(def y [1 2 3 4 5])
(def z [1 2 3 4 5 6 7])

(map + x y z)    ; yields (3 6 9 12)

この場合、どうすれば x と y をゼロでパディングし、この結果を得ることができますか:

(3 6 9 12 10 6 7)
4

2 に答える 2

12

mapそれ自体は行いませんが、 と の組み合わせを使用concatrepeatて、目的の結果を得ることができます。

(def x [1 2 3 4])
(def y [1 2 3 4 5])
(def z [1 2 3 4 5 6 7])

(map +
     (concat x (repeat 0))
     (concat y (repeat 0))
     z) ; => (3 6 9 12 10 6 7)

concatrepeatの API ドキュメントは次のとおりです。

そして、これを少し抽象化する方法のスケッチを次に示します。そのため、どのコレクションが最も長いかを知る必要はありません。(上記のスニペットでは、concatすべてのコレクションに(repeat 0)無限のシーケンスがある場合)。

(defn map-longest
  [f default & colls]
  (lazy-seq
   (when (some seq colls)
     (cons
      (apply f (map #(if (seq %) (first %) default) colls))
      (apply map-longest f default (map rest colls))))))

(map-longest +
             0
             [1 2 3 4]
             [1 2 3 4 5]
             [1 2 3 4 5 6 7]) ; => (3 6 9 12 10 6 7)

Stack Overflow に関するこの前の質問に対する回答として、他のいくつかのアプローチを確認できます。

于 2013-09-22T05:39:27.147 に答える
0

次の関数を使用して、可変長のマップのベクトルをマージできます。

(defn merge-maps
  [& args]
  (let [max-count (apply max (map #(count %1) args))
        items (map #(take max-count (concat %1 (repeat nil))) args)]
    (apply map merge items)))

この関数は解をより一般化し、マップの任意の長さのベクトルを取ることができます。

于 2019-08-21T05:26:20.573 に答える