2017-03-19 18 views
0

リストにある複数のマップをマージしたい。各マップには、2つのキーと値のペアがあります。私が持っているもの複数のマップをマージしてリストに値を保存する

...私が欲しいもの

val input = List[Map[String, String]] 
Map[a -> b, c -> d], 
Map[a -> b, c -> e], 
Map[a -> f, c -> h] 

...

val output = Map[String, List[String]] 
Map[b -> (d, e), f -> (h)] 

私が研究してきたが、私は見つけることができる最も近い、これはされていない、(Scala: Merge maps by key)でした私が探しているシナリオ。理想的には、単なるコード行ではなく、説明に感謝します。これはfor-loopsで行うことができますが、マップをマージするScalaの方法を学ぼうとしています。

編集:コメントでの議論の後、私は少し質問を単純化することに決めました。キー 'a'と 'c'は静的/関連性がない/ハードコーディングできます。

目標は、キー 'a'に関連付けられた値がキーになり、キー 'c'に関連付けられた値が値になる新しいマップを作成することです。すべての新しいマップが作成されたら、類似したキーを持つマップをグループ化して、それらの値をすべてリストに入れることができます。

+0

なぜ例えば、 'f'がキーになり、' h'が値になりますが、それ以外の方法ではありませんか?定義上、 'Maps'は順序付けされていないので、どの値がキーになり、どの値が値リストのメンバーになるかを決めるためにどのような規則が使われるかを指定する必要があります。 – jwvh

+0

多くの 'f'値(またはb)が繰り返されるため、それらをキーにするのがよりクリーンです。すべての 'h'値(またはd/e)はユニークな値なので、リスト内でグループ化することができます。 –

+0

コメントを削除して申し訳ありません、それは事故でした。あぁ、了解。説明ありがとう。 – Tanjin

答えて

1

OK、これを試してみてください。

val input: List[Map[String, String]] = List(Map("a" -> "b", "c" -> "d") 
              , Map("a" -> "b", "c" -> "e") 
              , Map("a" -> "f", "c" -> "h") 
              ) 

input.map(m => (m("a"), m("c"))) //List((b,d), (b,e), (f,h)) 
    .groupBy(_._1)    //Map(b -> List((b,d), (b,e)), f -> List((f,h))) 
    .mapValues(_.map(_._2))  //Map(b -> List(d, e), f -> List(h)) 
  1. は、第二の要素を抽出することにより、第一の要素のタプル(複数可)
  2. 非組の鍵を作るの値を取得し、タプルに入れ
+0

これは動作します!私は各ステップで何が起こっているのか理解しています(あなたのインラインコメントのおかげで)、括弧の中で使った表記の詳細はどこで知ることができますか?例えば、私はこれが何を意味するのか分かりません:(_._ 1) –

+0

@DWilliams、最初のアンダースコアは、無名関数(ラムダ)に渡された引数の省略形です。つまり、現在のコレクションの各要素のスタンドインです'List'や' Map'など)。 2番目のアンダースコアは、タプル要素にアクセス/抽出するためのメカニズムです。それは[ここ](http://stackoverflow.com/documentation/scala/4971/tuples#t=201703192204320234954)と[ここ](http://stackoverflow.com/documentation/scala/930/extractors/3070/tuple)に記載されています。 -extractors#t = 201703192159581456976)。 – jwvh

0

アイデアが最初groupByを使用して、最終的に値をマッピングする前に、すべての(key, value)ペアを抽出することである。

val input: List[Map[String, String]] = ... 

val res: Map[String, List[String]] = 
    input 
    .flatten      // List[(String, String)] 
    .groupBy { case (k, v) => k } // Map[String, List[(String, String)]] 
    .mapValues { _.map { case (k, v) => v } } // Map[String, List[String]] 
+0

'mapValues'はレイジーコレクションを返します。 –

関連する問題