[解決済み] 2つのマップをマージし、同じキーの値を合計するための最良の方法?
質問
val map1 = Map(1 -> 9 , 2 -> 20)
val map2 = Map(1 -> 100, 3 -> 300)
それらをマージして、同じキーの値を合計したいのです。その結果、次のようになる。
Map(2->20, 1->109, 3->300)
これで2つの解決策ができました。
val list = map1.toList ++ map2.toList
val merged = list.groupBy ( _._1) .map { case (k,v) => k -> v.map(_._2).sum }
そして
val merged = (map1 /: map2) { case (map, (k,v)) =>
map + ( k -> (v + map.getOrElse(k, 0)) )
}
しかし、もっと良い解決策があれば知りたい。
どのように解決するのですか?
スカラ座 という概念があります。 セミグループ これは、あなたがここでやりたいことをキャプチャし、間違いなく最も短く、最もきれいな解決策につながるものです。
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> val map1 = Map(1 -> 9 , 2 -> 20)
map1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 9, 2 -> 20)
scala> val map2 = Map(1 -> 100, 3 -> 300)
map2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 100, 3 -> 300)
scala> map1 |+| map2
res2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 109, 3 -> 300, 2 -> 20)
具体的には、二項演算子で
Map[K, V]
はマップのキーを結合し
V
の半群演算子で重複する値を処理します。 の標準的な半グループは
Int
は加算演算子を使うので、重複するキーごとに値の合計が得られます。
編集 : user482745さんのリクエストにより、もう少し詳しく。
数学的に
半グループ
は、単に値の集合と、その集合から2つの値を取り、その集合から別の値を生成する演算子です。 ですから、足し算の整数は半群になります。
+
演算子は2つのintを組み合わせて別のintを作る。
また、2つのマップを組み合わせて、何らかの形で2つの入力の組み合わせである新しいマップを生成する操作を思いつく限り、"与えられたキー型と値型を持つすべてのマップ"のセットに対する半グループを定義することも可能です。
両方のマップに現れるキーがない場合、これは些細なことです。 両方のマップに同じキーが存在する場合、そのキーが対応する2つの値を結合する必要があります。 同じ型の2つの実体を結合する演算子を説明しただけではないか? というわけで、Scalazでは
Map[K, V]
のための半グループが存在する場合に限り、存在する。
V
が存在する-。
V
の半グループは、同じキーに割り当てられている2つのマップの値を結合するために使われます。
というのは
Int
が値型であるため、この例では
1
キーは、マッピングされた2つの値の整数加算によって解決されます(Intの半群演算子がそうであるように)、したがって
100 + 9
. もし値がStringであれば、衝突は2つのマッピングされた値の文字列連結という結果になります(これもStringの半グループ演算子がそうするため)。
(そして興味深いことに、文字列の連結は可換でないため、つまりは
"a" + "b" != "b" + "a"
- その結果、半群演算もそうではありません。 つまり
map1 |+| map2
とは異なります。
map2 |+| map1
はStringの場合ですが、Intの場合はそうではありません)。
関連
-
[解決済み] Sparkです。CoarseGrainedSchedulerが見つかりませんでした。
-
[解決済み] SparkはYarnクラスタ上で動作しています exitCode=13:
-
[解決済み] Scalaの「コンテキストバウンド」とは何ですか?
-
[解決済み] git merge` で `--no-ff` フラグはどのような効果がありますか?
-
[解決済み] gitのマージ戦略を使い分けるとしたら、どんなとき?
-
[解決済み】JavaScriptで2つの配列を結合し、項目の重複を排除する方法
-
[解決済み】ScalaでVectorを選択するのはどんなとき?
-
[解決済み】「git merge」と「git rebase」の違いは何ですか?
-
[解決済み】Scalaの名前による呼び出しと値による呼び出し、明確化の必要性
-
[解決済み】ScalaのJavaConvertersとJavaConversionsの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Seq[Future[Person]]ではなく、Future[Seq[Person]]を取得する方法
-
[解決済み] A の値をキーとして Seq[A] を Map[Int, A] に変換する方法は?
-
[解決済み] Scala 無名クラスでextendsを使用する方法
-
[解決済み] scala.Float to java.Float k/v変換でScala MapをJava Mapに変換するにはどうしたらいいですか?
-
[解決済み] scalaのforeachループ
-
[解決済み] MapのmapValuesとtransformの違いについて
-
[解決済み] Scalaのオブジェクトとクラスの違い
-
[解決済み] self-typesとtrait subclassの違いは何ですか?
-
[解決済み] Traitの代わりに抽象クラスを使用する利点は何ですか?
-
[解決済み] Scalaの==と.equalsの違いは何ですか?