Reputation: 185
I have a List(List("aba, 4"), List("baa, 2"))
and I want to convert it into a map:
val map : Map[String, Int] = Map("aba" -> 4, "baa" -> 2)
What's the best way to archive this?
UPDATE:
I do a database query to retrieve the data: val (_, myData) = DB.runQuery(...)
This returns a Pair but I'm only interested in the second part, which gives me:
myData: List[List[String]] = List(List(Hello, 19), List(World, 14), List(Foo, 13), List(Bar, 13), List(Bar, 12), List(Baz, 12), List(Baz, 11), ...)
Upvotes: 1
Views: 2120
Reputation: 10571
Yet another take:
List(List("aba, 4"), List("baa, 2")).
flatten.par.collect(
_.split(",").toList match {
case k :: v :: Nil => (k, v.trim.toInt)
}).toMap
Differences to the other answers:
.par
to parallelize the creation of the pairs, which allows us to profit from multiple cores.collect
with a PartialFunction
to ignore strings that are not of the form "key, value"Edit: .par
does not destroy the order as the answer state previously. There is only no guarantee for the execution order of the list processing, so the functions should be side-effect free (or side-effects shouldn't care about the ordering).
Upvotes: 4
Reputation: 41646
scala> val pat = """\((.*),\s*(.*)\)""".r
pat: scala.util.matching.Regex = \((.*),\s*(.*)\)
scala> list.flatten.map{case pat(k, v) => k -> v.toInt }.toMap
res1: scala.collection.immutable.Map[String,Int] = Map(aba -> 4, baa -> 2)
Upvotes: 8
Reputation: 5224
List(List("aba, 4"), List("baa, 2")).
flatten. //get rid of those weird inner Lists
map {s=>
//split into key and value
//Array extractor guarantees we get exactly 2 matches
val Array(k,v) = s.split(",");
//make a tuple out of the splits
(k, v.trim.toInt)}.
toMap // turns an collection of tuples into a map
Upvotes: 1
Reputation: 340733
My take:
List(List("aba, 4"), List("baa, 2")) map {_.head} map {itemList => itemList split ",\\s*"} map {itemArr => (itemArr(0), itemArr(1).toInt)} toMap
In steps:
List(List("aba, 4"), List("baa, 2")).
map(_.head). //List("aba, 4", "baa, 2")
map(itemList => itemList split ",\\s*"). //List(Array("aba", "4"), Array("baa", "2"))
map(itemArr => (itemArr(0), itemArr(1).toInt)). //List(("aba", 4), ("baa", 2))
toMap //Map("aba" -> 4, "baa" -> 2)
Your input data structure is a bit awkward so I don't think you can optimize it/shorten it any further.
Upvotes: 1