Вы можете использовать тот факт, что массивы неявно преобразуются в 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]]
и наоборот:
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])
Я знаю, он не отвечает на вопрос, но зачем вам делать такую дифференциацию? Возможно, если вы дадите больше контекста, мы могли бы обходиться таким образом, чтобы определение не требовалось. (кстати, есть методы * .to [...] * *) –
Да, я знаю, что это довольно странно, и я бы не встретил это нормально :-) Я разбиваю чей-то контрольный код и хотел бы включить два дополнительных случаев, один для Array и один для списков. Я знаю, что это может быть решение, но я также хотел бы, чтобы это было просто, чтобы убедить его, что Скала крута и лаконична :-) – rlegendi
Вы можете использовать оболочку для 'Array' и использовать' s' как 'Seq [T]': 'if (true) Array (1): Seq [Int] else List (1)'. Вы получите 'res0: Seq [Int] = WrappedArray (1)'. – senia