可能是一个菜鸟问题,但我想在一个简短的脚本中做这样的事情:
val s = if ( <some condition> ) Array(...) else List(...)
print(s.length)
因为Object
和Array
没有共同的超类,所以s将被推断为List
。因此,第二行会出现错误,因为Object
没有length
方法。
提前致谢!
更新
呸,很遗憾我不能接受多个答案!谢谢你的帮助,伙计们!我和斯卡拉玩了很长一段时间,但似乎我还有很多需要学习的东西: - )
答案 0 :(得分:4)
您可以使用Array
的包装,并使用s
作为Seq[T]
:
scala> val s = if (true) Array(1): Seq[Int] else List(1)
s: Seq[Int] = WrappedArray(1)
对于多维数组,您可以像这样创建自己的转换器:
implicit class ArrArrWrap[T](a: Array[Array[T]]) extends IndexedSeq[WrappedArray[T]] {
def length = a.length
def apply(idx: Int) = a(idx): WrappedArray[T]
}
用法:
scala> val s = if (true) Array(Array(1)): Seq[Seq[Int]] else List(List(1))
s: Seq[Seq[Int]] = (WrappedArray(1))
将多维数组用作多维序列的想法有一个很大的缺点:
它涉及对除最后一个维度以外的每个维度的访问权限的转换。
s(0) // <- conversion here
因此可能会导致性能问题。将Array
转换为Seq
:
scala> val s = if (true) Array(Array(1)).map{ i => i: Seq[Int] }(breakOut) else List(List(1))
s: scala.collection.immutable.Seq[Seq[Int]] = Vector(WrappedArray(1))
答案 1 :(得分:2)
我认为Scala Iterable特性涵盖了这个用例:http://www.scala-lang.org/api/current/index.html#scala.collection.Iterable 我对Scala也很吵。
答案 2 :(得分:1)
您可以使用数组隐式转换为ArrayOps的事实,这使得它们可用作标准集合。基本上你需要做的就是选择ArrayOps
和List
共有的合适接口,并将其声明为变量的显式类型以触发转换:
val s: collection.SeqLike[Int,_] =
if (condition) Array(1, 2, 3)
else List(1, 2, 3, 4);
print(s.size)
更新:对于多维数组,您还需要在内部触发隐式转换,因为Array[ArrayOps[X]]
无法分配给Array[Array[X]]
,反之亦然:< / p>
type SL[+A] = SeqLike[A,_]
val s1: SL[SL[Int]] =
if (x) Array(Array(1, 2, 3): SL[Int]) else List(List(1, 2, 3, 4));
print(s1.size)
列表不需要它,因为它们的类型参数是协变的,因此当它们的一个超级接口使用时,它们可以在任何地方使用。
如果您是从一组固定的元素自己创建数组,则可以创建辅助函数,返回两个可能的包装器之一(ArrayOps
和WrappedArray
)。然后你不需要任何明确的输入:
import scala.collection.mutable._
import scala.reflect.ClassManifest
// Using ArrayOps
def arrayO[A: ClassManifest](xs: A*): ArrayOps[A] = Array(xs : _*);
val s2 =
if (x) arrayO(arrayO(1, 2), arrayO(3)) else List(List(1, 2), List(3, 4));
println(s2.size)
// UsingWrappedArray
def arrayW[A: ClassManifest](xs: A*): WrappedArray[A] = Array(xs : _*);
val s3 =
if (x) arrayW(arrayW(1, 2), arrayW(3)) else List(List(1, 2), List(3, 4));
println(s3.size)
如果您要包装现有数组,则需要像
一样包装每个级别val a4 = Array(Array(1, 2, 3), Array(5, 6));
val s4: SL[SL[Int]] = a.map(x => x: SL[Int])