Scala表打印

时间:2019-03-11 01:47:52

标签: scala

我是Scala的新手。我想找出一种打印不可变数据的方法,该数据是带有键的映射,键是字符串的元组,值是双精度值:

Map(
 ("ZZ1", "A") -> 3.5,
 ("ZZ2", "C") -> 2.3,
 ("ZZ3", "D") -> 2.8,
 ("ZZ1", "D") -> 3.0,
 ("ZZ2", "D") -> 5.9
)

想法是最终得到类似于没有值的零填充表格的打印结果(下图中的示例)。

table print

如何执行这种避免循环的方法?

预先感谢

2 个答案:

答案 0 :(得分:2)

也许是这样?

val data = Map(
 ("ZZ1", "A") -> 3.5,
 ("ZZ2", "C") -> 2.3,
 ("ZZ3", "D") -> 2.8,
 ("ZZ1", "D") -> 3.0,
 ("ZZ2", "D") -> 5.9
)

val (rows, cols) = {
  val (r, c) = data.keys.unzip
  (r.toList.sorted, c.toList.sorted)
}

val table = 
  ("" +: cols).map("%5s".format(_)).mkString + "\n" +
  rows.map { r =>
    "%5s".format(r) + cols.map { c =>
      " %4.1f".format(data.getOrElse((r, c), 0.0))
    }
    .mkString
  }.mkString("\n")

println(table)

礼物:

         A    C    D
  ZZ1  3.5  0.0  3.0
  ZZ2  0.0  2.3  5.9
  ZZ3  0.0  0.0  2.8

我并没有尝试使所有空间看起来都与图像中的完全一样,有更好的工具(TeX,CSS)。

答案 1 :(得分:1)

鉴于您的数据结构,您可以按元组的第一列进行分组,然后按如下所示手动提取值。

您有一个循环可用于分组(内部循环可循环访问分组的值,这意味着O(n^2)),循环到每个循环可打印(O(n))。

val data = Map(("ZZ1", "A") -> 3.5,
               ("ZZ2", "C") -> 2.3,
               ("ZZ3", "D") -> 2.8,
               ("ZZ1", "D") -> 3.0,
               ("ZZ2", "D") -> 5.9)

val group = data.groupBy{case (k, v) => k._1}.map { case (k, v) =>
    k -> v.map { case (k1, v1) => k1._2 -> v1 }
}

val Separator = "     "
println(s"${Separator}A ${Separator}B${Separator}C${Separator}D")

group.foreach {case (k, v) =>
    println(
      k + " " + 
      v.get("A").getOrElse(0.0) + Separator + 
      v.get("B").getOrElse(0.0) + Separator + 
      v.get("C").getOrElse(0.0) + Separator + 
      v.get("D").getOrElse(0.0))
}

结果:

      A      B       C       D
ZZ1 3.5     0.0     0.0     3.0
ZZ3 0.0     0.0     0.0     2.8
ZZ2 0.0     0.0     2.3     5.9

这里是运行示例-https://scastie.scala-lang.org/prayagupd/ZaK6hk2gRbSd6Yq1op7N1Q