我创建了一个数据结构来表示一个n * n * n立方体,在这种特殊情况下它是一个4 * 4 * 4的立方体。出于调试的目的,我想实现一个将多维数据集打印到stdout的方法。结果应该是4层,每层由4x4区域组成。
因为我正在学习Scala,所以我希望以“功能性方式”来实现,并提出了递归解决方案。 drawCube
方法在所有图层上“循环”,drawLayer
方法遍历图层的线条,drawLine
方法负责一行。
代码:
def drawCube = {
val n = cube.sidelength
val nl = sys.props("line.separator")
val border = " -" * (n * 2 -1)
def drawLine(acc: String, x: Int, y: Int, z: Int): String = {
if(x < n) drawLine(acc + getField(x, y, z), x + 1, y, z) else <PosA> + acc + "/" + nl
}
def drawLayer(acc: String, y: Int, z: Int): String = {
if(z >= 0) drawLayer(<PosB> + drawLine(acc, 0, y, z), y, z - 1) else acc + border + nl
}
def drawCube(acc: String, y: Int): String = {
if(y < n) drawCube(drawLayer(acc, y, n - 1), y + 1) else border + nl + acc
}
def getField(x: Int, y: Int, z: Int) = {
// returns a string representation of a specific field from the cube
// in the following example, it's just a dot for the sake of simplicity
// in a 4x4x4 cube, the range of x, y and z is from 0 to 3
}
println(drawCube("", 0))
}
无论我是否在位置A 或位置B (请参阅上面的占位符)中添加额外的“/”,我总是得到以下结果:
- - - - - - -
//////////////// . . . . /
. . . . /
. . . . /
. . . . /
- - - - - - -
. . . . /
. . . . /
. . . . /
. . . . /
- - - - - - -
. . . . /
. . . . /
. . . . /
. . . . /
- - - - - - -
. . . . /
. . . . /
. . . . /
. . . . /
- - - - - - -
正如你所看到的,一切都运行正常,除了前导斜杠,它们都是一次打印而不是一行的开头。这是为什么?什么是正确的位置?也许我花了太多时间用它,但我现在看不出问题。谢谢。
编辑:你可能已经注意到drawLayer方法的停止条件与其他两个方法相比略有不同。这与坐标系的变换有关,原点应显示在左上角。但我不认为这是问题,字段显示在正确的位置。
答案 0 :(得分:1)
功能风格的巨大优势在于您可以单独测试较小的方法。尝试单独测试drawLine
,或者用更简单的方法替换drawLine
并测试drawLayer
。我建议在基本功能正常工作之前避开累加器 - 简单的0 until n map {drawLine(_, y, z)} mkString
可能会出错。
要回答您的具体问题,累加器始终是多维数据集的完整当前图形,以及任何函数的返回值。所以你不能"/" + acc
或"/" + drawSomething()
,因为这总是会在开头添加“/”。相反,您需要在调用acc
之前将“/”添加到drawLine
的 end ,。即drawLayer
应定义为:
def drawLayer(acc: String, y: Int, z: Int): String =
if(z >= 0) drawLayer(drawLine(acc + "/", 0, y, z), y, z - 1) else acc + "-" + "\n"