crockpotveggies
crockpotveggies

Reputation: 13300

Scala combine separate List[Map[String,Any]] into one list and concat Maps

I have two lists of List[Map[String,String]] where the second list of Maps has a key "stringKey" that matches a single "stringKey" in the first list of Maps. I need to combine both lists into one and append the values of the second Map into the first.

Catch is that second list of Maps may have duplicate keys as first list, but those can be discarded. I was thinking of using scalaz subgroups for this but got lost on discarding duplicates. Here's an example of the two types of Maps below:

Map 1 in 1st list: List(Map("stringKey" -> "a0sd8fa0s8df", "name" -> "#hashtag", "updated" -> "88493048"))

Map 2 in 2nd list: List(Map("stringKey" -> "a0sd8fa0s8df", "points" -> "1000", "updated" -> "88773055"))

Result would be List(Map("stringKey" -> "a0sd8fa0s8df", "name" -> "#hashtag", "points" -> "1000"))

I'm guessing merging the two lists would be a start. Any ideas from there? Thanks!

Update

I've got this so far but it gives me a List[Option[String],List[Map[String,String]]]

l1 ++ l2 groupBy ( _.get("stringKey") )

Upvotes: 1

Views: 1185

Answers (2)

Keith Pinson
Keith Pinson

Reputation: 1725

val listA = List(Map("stringKey" -> "a0sd8fa0s8df", "name" -> "#hashtag", "updated" -> "88493048"))
val listB = List(Map("stringKey" -> "a0sd8fa0s8df", "points" -> "1000", "updated" -> "88773055"))

List((listA ++ listB).flatMap(a=>a).toMap)

Res7: List[scala.collection.immutable.Map[String,String]] = List(Map(stringKey -> a0sd8fa0s8df, name -> #hashtag, updat ed -> 88773055, points -> 1000))

If you only want the unique key,value pairs:

val a = (listA ++ listB).flatMap(a=>a)
List(a.filter( s => a.distinct.count( t => t._1 == s._1 ) <= 1 ).distinct.toMap)

res20: List[scala.collection.immutable.Map[String,String]] = List(Map(stringKey -> a0sd8fa0s8df, name -> #hashtag, point s -> 1000))

Upvotes: 1

Eugene Ryzhikov
Eugene Ryzhikov

Reputation: 17359

Sounds like each Map in the list represents a unique object. I would convert first List of Maps into Map of Maps where the key is a value of the "stringKey" (sounds like a unique id to me).

Having at least one such Map you can simply walk through the other list, quickly find sub-maps in the list by stringKey and update them.

If you need to - you can convert Map of Maps back to a List of Maps.

All this BTW sounds like good job for the foldLeft on List2

UPDATE: This is what I came up with so far.. seems to do what you need.

val lst1 = List(Map("stringKey" -> "a0sd8fa0s8df", "name" -> "#hashtag", "updated" -> "88493048"))
val lst2 = List(Map("stringKey" -> "a0sd8fa0s8df", "points" -> "1000", "updated" -> "88773055"))

val result = lst2.foldLeft( lst1.map( x => (x("stringKey") -> x ) ).toMap) { (m,v) =>
    val id = v("stringKey")
    m + ( id -> ( m.getOrElse( id, Map()) ++ v) )
 }.values.toList 

Upvotes: 2

Related Questions