Scala Map Merge

http://www.nimrodstech.com/scala-map-merge/

Need to merge multiple maps by their keys and make manipulation on the values? this post is probably for you!
Why ?previous experience with map reduce, many times data collected was in a Map structure, found myself repeatedly summing/appending/listing/manipulating maps

Assuming we have 2 maps with names of people as the key and the amount of them as the value :

 //each map contains count of people names
 val names = Map("Sidney" -> 1, "Paul" -> 1, "Jacob" -> 7)
 val moreNames = Map("Sidney" -> 1, "Paul" -> 5, "Nick" -> 2)

For some reason we need to merge the 2 maps into 1 expecting to sum the values and get all keys.

 //need to merge them to 1 map that sums all people names
 //expecting : Map("Sidney" -> 2, "Paul" -> 6, "Nick" -> 2, "Jacob" -> 7)

Lets write our own implementation for this task :

 //note ++ on maps will get all keys with second maps values if exists, if not first map values.
 val mergedMap = names ++ moreNames.map {
    case (name,count) => name -> (count + names.getOrElse(name,0)) }

Next task: lets merge the maps but instead of summing the values lets list them

 //expecting : Map("Sidney" -> List(1,1), "Paul" -> List(5,1), "Nick" -> List(2), "Jacob" -> List(7))
 val mergedMap2 = (names.toSeq ++ moreNames.toSeq)
  .groupBy{case(name,amount) => name}
  .mapValues(person => person.map{ case(name,amount) => amount}.toList)

Ok that was nice, but can be achieved much easier using Scalaz semigroups

//in your projects dependencies
val scalazDep = Seq (org.scalaz %% scalaz-core % 7.0.6)
 //now lets use scalaz Semigroup concept
 //lets merge maps by key and sum the values !
 import scalaz.Scalaz._
 val mergedMap3 = names |+| moreNames
 //lets merge maps by key and list the values
 val mergedMap4 = names.map(p => p._1 -> List(p._2)) |+| moreNames.map(p => p._1 -> List(p._2))

Main idea with using scalaz |+| is to arrange the data structure to what you need to do. in case you need to sum values a int will do the job. case you need to list the values a list of Any will do the trick.
This example really comes in handy when used in reduce functions, resulting in clean and short code (if you aren’t a scalaz hater)

 //each map contains count of people names
 val names = Map("Sidney" -> 1, "Paul" -> 1, "Jacob" -> 7)
 val moreNames = Map("Sidney" -> 1, "Paul" -> 5, "Nick" -> 2)
 //Money time!
 val test = List(names , moreNames).reduce(_ |+| _)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 13,478评论 0 23
  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的阅读 14,596评论 5 6
  • 我,一个毕业于,211工程大学的本科生,从一开始参加工作。一直到六年后的今天,我的窗外,没有变化过,或者,一直在重...
    11号楼阅读 2,206评论 0 0
  • 梦 你笑 说无知 不可办到 我不理不睬 在似水流年间 我选了风雨照料 不愿做命运的农奴 在风雨中学会了站立 冥冥中...
    程xi阅读 1,332评论 1 0
  • 杀人的心,有想,不敢; 自杀的心,有想,也不敢; 终究是缺了份跟死有关的勇气。 ———————————— 文明人活...
    smile丝唛小主阅读 1,722评论 0 0