在Scala中展开/组合多维数组?

时间:2013-03-03 21:05:45

标签: scala scala-collections scala-2.10

说我有一个例如二维数组,我在元组中存储一些索引:

val testArray = Array.ofDim[Double](3, 4)
val ixs = (1,2)

我想直接使用这些元组,例如testArray(ixs)。但是,Function.tupled(testedArray _)返回“_必须遵循方法;不能跟随数组[数组[双]]”。

这是因为Array实际上不是Function3的子类型吗? 如果是这样,如何解决这个限制?我应该使用implicits来扩展ArrayOps或类似内容吗?目前,我将数据存储在Map中作为解决方法。

1 个答案:

答案 0 :(得分:2)

阵列阵列没有得到特殊处理;他们只是(某事)的数组。因此,没有通过元组访问它们的特殊方法。但正如你所建议的,你可以创造这样一种方式。

你可以

implicit class ArrayOps2D[@specialized T](xss: Array[Array[T]]) {
  def apply(ij: (Int, Int)) = xss(ij._1)(ij._2)
  def apply(i: Int, j: Int) = xss(i)(j)
  def update(ij: (Int, Int), t: T) { xss(ij._1)(ij._2) = t }
  def update(i: Int, j: Int, t: T) { xss(i)(j) = t }
}

您可能会想到

implicit class ArrayOps2D[T](val xss: Array[Array[T]]) extends AnyVal {
  def apply(ij: (Int, Int)) = xss(ij._1)(ij._2)
  def apply(i: Int, j: Int) = xss(i)(j)
  def update(ij: (Int, Int), t: T) { xss(ij._1)(ij._2) = t }
  def update(i: Int, j: Int, t: T) { xss(i)(j) = t }
}

但在我看来,这并不奏效。由于实施限制,您无法专门化AnyVal。此外,前者可能更好,如果你使用原语很多,因为它避免装箱原语(并且JVM可以处理避免对象创建,希望如此),而后者在大多数时候有非原语时效率更高(因为你没有(正式)创建一个对象。但是你的例子使用了原语。

在任何情况下,如果你这样做,你将使用元组和参数对进行无缝的双索引寻址(就像我写的那样)。但无法完全无缝地使用更新方法!它们大部分都可以使用,但是不会自动提升数字类型。因此,如果你有双打并且你写a(1,2) = 3它会失败,因为它找不到update(Int, Int, Int)方法,并且不认为使用update(Int, Int, Double)。但是你可以通过转换来解决这个问题(或者在这种情况下写3d)。