【问题标题】:Scala recursive printing function for nested Arrays用于嵌套数组的 Scala 递归打印函数
【发布时间】:2018-09-23 07:33:07
【问题描述】:

我正在尝试编写一个可以打印任意嵌套数组的辅助方法。我的计划是编写一个递归方法来处理这个问题。我想用打字来区分调用哪个方法。

基本情况是打印一个包含值的数组,即不是另一个嵌套数组。

递归情况是如果数组包含另一个数组,则在子数组上调用 print。

这是我想写的代码

object Helper {

  // Takes something that is an array of arrays and prints it
  def print[B <: Array[Array[AnyVal]]](data: B): Unit = {
    val sb = new StringBuilder()
    printSb(data, sb)
    println(sb.toString())
  }
  // Same as above but with string builder
  private def printSb[B <: Array[Array[_]]](data: B, sb: StringBuilder): Unit = {
    data.foreach(arr => printSb(arr, sb))
  }

  // Prints a value
  def print[B <: AnyVal](data: Array[B]): Unit = {
    val sb = new StringBuilder()
    printSb(data, sb)
    println(sb.toString())
  }

  // Prints an Array of values, not an array or arrays
  private def printSb[B <: AnyVal](data: Array[B], sb: StringBuilder): Unit = {
    data.foreach(b => "%s ".format(sb.append(printVal(b))))
  }

  // Prints a value
  def printVal(v: Any): String = {
    v match {
      case b: Boolean => if (b) "1" else "0"
      case i: Integer => "%01d".format(i)
      case v => v.toString
    }
  }
}

但是,编译器很难决定将方法调用分派到哪个打印(我认为是因为 AnyVal == Array[_] ???)。我正在寻找一种通过类型表达我的要求的好方法,这可能吗?

【问题讨论】:

  • 您在呼叫站点有完整的类型信息,还是到处只有AnyVals?如果你有完整的信息,你可以用类型类做得更好。实际上,这与Show 非常相似。
  • @AndreyTyukin 是的,在呼叫现场会有完整的类型信息,我会研究类型类。您将如何在这个特定实例中使用类型类?
  • jwvh 的简单实用的解决方案让我的第一个提案有了正确的认识。如果递归调用预定义的toString 方法,分别处理数组,真的是你想要的,我宁愿使用jwvh 的解决方案,不需要过度设计它。如果您仍然对基于类型类的解决方案感兴趣,只需查看 scala-cats 中的 Show 实现即可。如果您想用其他东西替换相关对象的预定义toString,这可能很有用。
  • 感谢您的信息,将尝试使用 Show 的模式来实现 :) def 喜欢 jwvh 的简单解决方案。

标签: arrays scala recursion types polymorphism


【解决方案1】:

在我看来,你让这变得比它需要的更复杂。

从简单的开始...

def stringAll[X](x :X) :String = x match {
  case arr: Array[_] => arr.map(stringAll).mkString("["," ","]")
  case _ => x.toString
}

...有效...

val a = Array(Array(Array(2,5),Array('c','t')))
stringAll(a)  //res0: String = [[[2 5] [c t]]]

...并根据需要添加更高级的转换,case b:Boolean =&gt; ...

【讨论】:

  • 很酷的答案,绝对比我尝试做的要简单得多。区分 [][] 案例和 [] 案例也很容易。 def stringAll[X](x :X) :String = x match { case arr: Array[Array[]] => arr.map(stringAll).mkString("\n"," ","\n ") case arr: Array[] => arr.map(stringAll).mkString(""," ","\n") case b: Boolean => if (b) "1" else "0 " case _ => x.toString }
猜你喜欢
  • 2015-10-24
  • 1970-01-01
  • 2020-03-09
  • 2020-09-05
  • 1970-01-01
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
  • 2010-12-18
相关资源
最近更新 更多