Reputation: 89
I have a Map[String, String].
Edit: val m: Map[String, Any] = Map("a" -> Map("b" -> Map("c" -> "e", "d" -> "g")))
Is there a way to convert my Map[String,Any] to Map[String,String]
What is the best way to convert this nested Map into another Map with values like
Map("a.b.c" -> "e", "a.b.d" -> "g")
I found an earlier solution that is for Map[String,Int]. The link is given here: How to make a nested map as dot separated strings of key and value in scala
I tried to change the code (given in the comments of the above question):
def traverse(el: String, acc: List[String] = List.empty[String]): Map[String, String] = el match {
case leaf: String => Map(acc.reverse.mkString(".") -> leaf)
case m: Map[String, String] => m flatMap {
case (k, v) => traverse(v, k :: acc)
}
}
traverse(m)
However, i get the following error: Scrutinee is incompatible with pattern type, found: Map[String, String], required: String
I am new to Scala, so am unable to modify the code, please suggest what is causing this.
Update Solution:
def unravel(badmap :Map[String,_]
,key:List[String] = Nil) :Map[String,String] =
badmap.foldLeft(Map.empty[String,String]){
case (m,(k,v)) if v.isInstanceOf[Map[_,_]] =>
println("Case1" + m)
m ++ unravel(v.asInstanceOf[Map[String,_]], k::key)
case (m,(k,v)) =>
println("Case2: " + m)
val tempv = if (v!=null) v.toString else null
m + ((k::key).reverse.mkString(".") -> tempv )
}
I had a null value which caused it to fail. I updated the solution given. Thank you!
Upvotes: 1
Views: 766
Reputation: 51271
You're in a bad place (type Any
).
Sometimes we have to use unwise and unsafe tools (runtime type casting) to get out of a bad situation.
def unravel(badmap :Map[String,_]
,key:List[String] = Nil) :Map[String,String] =
badmap.foldLeft(Map.empty[String,String]){
case (m,(k,v)) if v.isInstanceOf[Map[_,_]] =>
m ++ unravel(v.asInstanceOf[Map[String,_]], k::key)
case (m,(k,v)) =>
m + ((k::key).reverse.mkString(".") -> v.toString)
}
testing:
val m: Map[String, _] =
Map("a" -> Map("b" -> Map("c" -> "e", "d" -> "g")))
unravel(m)
//res0: Map[String,String] = Map(a.b.c -> e, a.b.d -> g)
Much better to avoid situations like this. Go back and fix the code that produced that Map
.
Upvotes: 1