Suppose I have a nexted Map in Scala as below:
type MapType = Map[String, Map[String, Map[String, (String, String)]]]
val m: MapType = Map("Alphabet" -> Map( "Big Boss" -> Map("Clandestine Mssion" -> ("Dracula Returns", "Enemy at the Gates"))))
println(m)
This would output the Map as shown below:
Map(Alphabet -> Map(Big Boss -> Map(Clandestine Mssion -> (Dracula Returns,Enemy at the Gates))))
How can I print it like below instead?:
Map(
Alphabet -> Map(Big Boss -> Map(
Clandestine Mssion -> (Dracula Returns,Enemy at the Gates)
)
)
)
Or in a way that is similar to pretty nested JSON.
This should do the trick
object App {
def main(args : Array[String]) {
type MapType = Map[String, Map[String, Map[String, (String, String)]]]
val m: MapType = Map("Alphabet" -> Map( "Big Boss" -> Map("Clandestine Mssion" -> ("Dracula Returns", "Enemy at the Gates"))))
println(m.prettyPrint)
}
implicit class PrettyPrintMap[K, V](val map: Map[K, V]) {
def prettyPrint: PrettyPrintMap[K, V] = this
override def toString: String = {
val valuesString = toStringLines.mkString("\n")
"Map (\n" + valuesString + "\n)"
}
def toStringLines = {
map
.flatMap{ case (k, v) => keyValueToString(k, v)}
.map(indentLine(_))
}
def keyValueToString(key: K, value: V): Iterable[String] = {
value match {
case v: Map[_, _] => Iterable(key + " -> Map (") ++ v.prettyPrint.toStringLines ++ Iterable(")")
case x => Iterable(key + " -> " + x.toString)
}
}
def indentLine(line: String): String = {
"\t" + line
}
}
}
The output is
Map (
Alphabet -> Map (
Big Boss -> Map (
Clandestine Mssion -> (Dracula Returns,Enemy at the Gates)
)
)
)
Here's an approach using type classes that avoids casting and toString
.
trait Show[A] {
def apply(a: A): String
}
object Show {
def apply[A](f: A => String): Show[A] =
new Show[A] {
def apply(a: A): String = f(a)
}
}
implicit def showString: Show[String] = Show(identity)
implicit def show2[A, B](implicit sA: Show[A], sB: Show[B]): Show[(A, B)] =
Show({ case (a, b) => s"(${sA(a)}, ${sB(b)})" })
implicit def showMap[A, B](implicit sA: Show[A], sB: Show[B]): Show[Map[A, B]] =
Show(m => s"Map(\n${
m.map({
case (a, b) => s" ${sA(a)} -> ${sB(b).replace("\n", "\n ")}"
}).mkString(",\n")
}\n)")
def show[A](a: A)(implicit s: Show[A]): String = s(a)
val m = Map("Alphabet" -> Map("Big Boss" -> Map("Clandestine Mission" ->
("Dracula Returns", "Enemy at the Gates"))))
show(m)
Result:
Map(
Alphabet -> Map(
Big Boss -> Map(
Clandestine Mission -> (Dracula Returns, Enemy at the Gates)
)
)
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With