Создание метода, который принимает любую 2D-последовательность и превращает ее в массив [Array [_]] в Scala

Как указано в заголовке, я хочу иметь метод, который можно применить к любому типу аргумента, например Array [Array [_]] или Seq [Array [_]] или Array [Seq [_]] или Seq [Seq [_]] . Аргумент должен быть преобразован в 2D-массив ( Array [Array [_]] ), тем самым изменяя только тип задействованных коллекций.

У меня есть следующая подпись, которая, похоже, принимает любую такую ​​комбинацию, но я не могу построить массивы.

  def apply[A: Manifest, S[_] <: Seq[_], U <% S[S[A]]](components: U): CombinationIterator[A] = {
    new CombinationIterator(Array(components.map((s: S[A]) => s.toArray)))
  }

Класс CombinationIterator принимает массив [Array [T]] в качестве аргумента. Я получаю следующую ошибку:

error: could not find implicit value for evidence parameter of type ClassManifest[A]
new CombinationIterator(Array(components.map((s: S[A]) => s.toArray)))

Для полноты, вот конструктор; возможно, это имеет значение, потому что требуется манифест для A .

class CombinationIterator[A: Manifest](components: Array[Array[A]]) extends Iterator[Array[A]]

сбой сеанса REPL

Для массива [Seq [_]] работает следующее ], но не для Seq [Array [_]] :

scala> def f[T:Manifest](s: Seq[Seq[T]]) = s.map(_.toArray).toArray
f: [T](s: Seq[Seq[T]])(implicit evidence$1: Manifest[T])Array[Array[T]]

scala> f(Array(Seq(1,2),Seq(3,4)))
res22: Array[Array[Int]] = Array(Array(1, 2), Array(3, 4))

scala> f(Seq(Array(1,2),Array(3,4)))
<console>:9: error: type mismatch;
 found   : Seq[Array[Int]]
 required: Seq[Seq[?]]
       f(Seq(Array(1,2),Array(3,4)))
            ^

(сбой) REPL для идеи Didierd

scala> def f[T: Manifest, ST <% Seq[T]](s: Seq[ST]) = s.map(_.toArray).toArray
f: [T, ST](s: Seq[ST])(implicit evidence$1: Manifest[T], implicit evidence$2: (ST) => Seq[T])Array[Array[T]]

scala> f(Seq(Seq(1)))
<console>:9: error: No implicit view available from Seq[Int] => Seq[T].
       f(Seq(Seq(1)))
        ^

Решение, которое я установил на

Следующий код работает для моего проекта. Может быть, охвачены не все частные случаи. Это вариант второго ответа Рекса.

Я чувствую, что имплициты хорошо заключены внутри сопутствующего объекта.

object CombinationIterator {
  case class AArray[T](aa: Array[Array[T]])
  implicit def seqseq2AA[T: Manifest](ss: Seq[Seq[T]]) = AArray(ss.map(_.toArray).toArray)
  implicit def seqarray2AA[T: Manifest](sa: Seq[Array[T]]) = AArray(sa.toArray)

  def apply[T: Manifest](components : AArray[T]): CombinationIterator[T] = {
    new CombinationIterator(components.aa)
  }
}

Править

Чтобы опубликовать более новую информацию о причинах вопроса. Я хотел иметь эти вложенные массивы из соображений производительности. Но для примитивных типов массивы важнее. Так что, вероятно, не так уж плохо - с точки зрения производительности - иметь внешний массив в качестве «правильной» структуры данных, например Vector .

5
задан ziggystar 15 March 2012 в 08:00
поделиться