如何获取嵌套的WrappedArray

时间:2015-10-16 13:05:38

标签: arrays scala collections

我需要具有快速索引访问和最小开销的只读结构。应用程序会经常查询该结构。因此,正如在网上所假设的那样,我尝试使用Array并将它们转换为IndexedSeq

scala> val wa : IndexedSeq[Int] = Array(1,2,3)
wa: IndexedSeq[Int] = WrappedArray(1, 2, 3)

到目前为止,这么好。但我需要使用嵌套的Array,问题就在于此。

 val wa2d : IndexedSeq[IndexedSeq[Int]] = Array(Array(1,2), Array(3), Array())
<console>:8: error: type mismatch;
found   : Array[Array[_ <: Int]]
required: IndexedSeq[IndexedSeq[Int]]
       val wa2d : IndexedSeq[IndexedSeq[Int]] = Array(Array(1,2), Array(3), Array())

Scala编译器无法递归地应用隐式转换。

scala> val wa2d : IndexedSeq[IndexedSeq[Int]] = Array(Array[Int](1,2) : IndexedSeq[Int], Array[Int](3) : IndexedSeq[Int], Array[Int]() : IndexedSeq[Int])
wa2d: IndexedSeq[IndexedSeq[Int]] = WrappedArray(WrappedArray(1, 2), WrappedArray(3), WrappedArray())

这是按预期工作的,但这个表单太冗长了,因为我需要两次指定类型的每个子数组。我想完全避免它。所以我尝试了另一种方法

scala> val wa2d : IndexedSeq[IndexedSeq[Int]] = Array(Array(1,2), Array(3), Array()).map(_.to[IndexedSeq])
wa2d: IndexedSeq[IndexedSeq[Int]] = ArraySeq(Vector(1, 2), Vector(3), Vector())

但所有WrappedArray神秘地消失了,并被ArraySeqVector取代。

那么定义嵌套WrappedArray的不那么模糊的方法是什么?

1 个答案:

答案 0 :(得分:1)

以下是您的操作方法:

scala> def wrap[T](a: Array[Array[T]]): IndexedSeq[IndexedSeq[T]] = { val x = a.map(x => x: IndexedSeq[T]); x }
scala> wrap(Array(Array(1,2), Array(3,4)))
res13: IndexedSeq[IndexedSeq[Int]] = WrappedArray(WrappedArray(1, 2), WrappedArray(3, 4))

如果您想使用隐式转换,请使用:

def wrap[T](a: Array[Array[T]]): IndexedSeq[IndexedSeq[T]] = { val x = a.map(x => x: IndexedSeq[T]); x }
implicit def nestedArrayIsNestedIndexedSeq[T](x: Array[Array[T]]): IndexedSeq[IndexedSeq[T]] = wrap(x)
val x: IndexedSeq[IndexedSeq[Int]] = Array(Array(1,2),Array(3,4))

这就是为什么你想要这样做的原因:

val th = ichi.bench.Thyme.warmed()
val a = (0 until 100).toArray
val b = a: IndexedSeq[Int]
def sumArray(a: Array[Int]): Int = { var i = 0; var sum = 0; while(i < a.length) { sum += a(i); i += 1 }; sum }
def sumIndexedSeq(a: IndexedSeq[Int]): Int = { var i = 0; var sum = 0; while(i < a.length) { sum += a(i); i += 1 }; sum }
scala> th.pbenchOff("")(sumArray(a))(sumIndexedSeq(b))
Benchmark comparison (in 439.6 ms)
Significantly different (p ~= 0)
  Time ratio:    3.18875   95% CI 3.06446 - 3.31303   (n=30)
    First     65.12 ns   95% CI 62.69 ns - 67.54 ns
    Second    207.6 ns   95% CI 205.2 ns - 210.1 ns
res15: Int = 4950

最重要的是,一旦通过WrappedArray [Int]间接访问Array [Int],基元就会被装箱。事情变得慢得多。如果您确实需要阵列的完整性能,则必须直接使用它们。如果你不这样做,只需使用Vector并停止担心它。

我会选择Vector进行原型设计,然后转到Array一次/如果你确定这实际上是一个性能瓶颈。使用类型别名,以便您可以快速从Vector切换到数组。

包对象中的某个地方:

type Vec[T] = Vector[T]
val Vec = Vector
// type Vec[T] = Array[T]
// val Vec = Array

然后你可以编写像这样的代码

val grid = Vec(Vec(1,2), Vec(3,4))

并快速切换到阵列版本,以防度量这实际上是性能瓶颈。