2

初めてみた

(merge-with list maps)

単一の値を持つマップで機能しますが、次のような場合

{:a [1 2]} {:a [2 3]} {:a [3 4]}

それは私に与えます

{:a (([1 2] [2 3]) [3 4])}

しかし、私はしたいです

{:a ([1 2] [2 3] [3 4])}

マップの値をベクトルでラップできることがわかりました。

(defn my-merge
  [& coll]
  (let [maps (map #(assoc % (first (keys %)) [(first (vals %))]) coll)]
    (apply merge-with concat maps)))

しかし、let バインディングはネストしすぎているようです。concat の代わりに使用できる簡単な関数はありますか? したがって、次のような1行のコードを作成できます。

(merge-with the-function maps)
4

3 に答える 3

0

以下の解決策では、リスト内のアイテムの順序がマップの順序に基づいていることも確認してください。

(def maps [{:a [1 2]} 
          {:a [2 3] :b :two} 
          {:a [3 4] :b :one}])

(into {} (for [k (into #{} (mapcat keys maps))
               :let [obj (Object.)]]
           [k (filter (partial not= obj)
                      (map #(get % k obj) maps))]))

=> {:a ([1 2] [2 3] [3 4]), :b (:two :one)}
于 2013-04-07T08:13:51.070 に答える
0

バージョン 1

(defn my-merge [f & mlist] 
  (into {} 
        (map (fn [[k v]] [k (apply f (map val v))]) 
             (group-by key (apply concat mlist)))))

(my-merge list
          {:a [1 2]} 
          {:a [2 3] :b :two} 
          {:a [3 4] :b :one})

=> {:a ([1 2] [2 3] [3 4]) :b (:two :one)}

バージョン 2

(defn my-merge [f initv & mlist] 
  (apply merge-with f 
         (apply merge-with (fn [_ _] initv) mlist)
         mlist))

(my-merge conj ()
          {:a [1 2]} 
          {:a [2 3] :b :two} 
          {:a [3 4] :b :one})

=> {:b (:one :two), :a ([3 4] [2 3] [1 2])}
于 2013-04-07T04:53:40.027 に答える