在Scala中初始化2D(多维)数组 [英] Initializing a 2D (multi-dimensional) array in Scala

查看:94
本文介绍了在Scala中初始化2D(多维)数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过在Java中放置类似这样的内容,可以很容易地初始化2D数组(或者实际上是任何多维数组):

It's easy to initialize a 2D array (or, in fact, any multidimensional array) in Java by putting something like that:

int[][] x = new int[][] {
        { 3, 5, 7, },
        { 0, 4, 9, },
        { 1, 8, 6, },
};

它易于阅读,类似于2D矩阵等.

It's easy to read, it resembles a 2D matrix, etc, etc.

但是我该如何在Scala中做到这一点?

But how do I do that in Scala?

我想出的最好的外观,简明扼要得多:

The best I could come up with looks, well, much less concise:

val x = Array(
    Array(3, 5, 7),
    Array(0, 4, 9),
    Array(1, 8, 6)
)

我在这里看到的问题:

  • 它一遍又一遍地重复数组"(就像Array之外可能还有其他东西一样)
  • 在每次调用数组时都需要省略尾随,
  • 如果我拧紧并在数组中间插入除Array()之外的内容,则对于编译器来说还可以,但是x的类型将默默地变为Array[Any]而不是Array[Array[Int]]: >

  • It repeats "Array" over and over again (like there could be anything else besides Array)
  • It requires to omit trailing , in every Array invocation
  • If I screw up and insert something besides Array() in the middle of array, it will go okay with compiler, but type of x would silently become Array[Any] instead of Array[Array[Int]]:

val x = Array(
    Array(3, 5, 7),
    Array(0, 4), 9, // <= OK with compiler, silently ruins x
    Array(1, 8, 6)
)

有一种防范措施,可以直接指定类型,但是它看上去比Java中的矫kill过正:

There is a guard against it, to specify the type directly, but it looks even more overkill than in Java:

val x: Array[Array[Int]] = Array(
    Array(3, 5, 7),
    Array(0, 4), 9, // <= this one would trigger a compiler error
    Array(1, 8, 6)
)

最后一个示例所需的Array甚至是我在Java中要说int[][]的三倍.

This last example needs Array even 3 times more than I have to say int[][] in Java.

有没有解决的办法?

推荐答案

我建议使用Scala 2.10和宏:

I suggest to use Scala 2.10 and macros:

object MatrixMacro {

  import language.experimental.macros

  import scala.reflect.macros.Context
  import scala.util.Try

  implicit class MatrixContext(sc: StringContext) {
    def matrix(): Array[Array[Int]] = macro matrixImpl
  }

  def matrixImpl(c: Context)(): c.Expr[Array[Array[Int]]] = {
    import c.universe.{ Try => _, _ }

    val matrix = Try {
      c.prefix.tree match {
        case Apply(_, List(Apply(_, List(Literal(Constant(raw: String)))))) =>

          def toArrayAST(c: List[TermTree]) =
            Apply(Select(Select(Ident("scala"), newTermName("Array")), newTermName("apply")), c)

          val matrix = raw split "\n" map (_.trim) filter (_.nonEmpty) map {
            _ split "," map (_.trim.toInt)
          }
          if (matrix.map(_.length).distinct.size != 1)
            c.abort(c.enclosingPosition, "rows of matrix do not have the same length")

          val matrixAST = matrix map (_ map (i => Literal(Constant(i)))) map (i => toArrayAST(i.toList))

          toArrayAST(matrixAST.toList)
      }
    }

    c.Expr(matrix getOrElse c.abort(c.enclosingPosition, "not a matrix of Int"))
  }

}

用法:

scala> import MatrixMacro._
import MatrixMacro._

scala> matrix"1"
res86: Array[Array[Int]] = Array(Array(1))

scala> matrix"1,2,3"
res87: Array[Array[Int]] = Array(Array(1, 2, 3))

scala> matrix"""
     |   1, 2, 3
     |   4, 5, 6
     |   7, 8, 9
     | """
res88: Array[Array[Int]] = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9))

scala> matrix"""
     |   1, 2
     |   1
     | """
<console>:57: error: rows of matrix do not have the same length
matrix"""
^

scala> matrix"a"
<console>:57: error: not a matrix of Int
              matrix"a"
              ^

我不认为您会更短. ;)

I don't think you will get it shorter. ;)

这篇关于在Scala中初始化2D(多维)数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆