创建一个采用任何2D序列并将其转换为Scala中的数组[Array [_]]的
正如标题所述,我希望有一个方法可以应用于任何类型的参数,如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 [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会话 以下适用于Array [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,Array(3,4)) scala> f(Seq(Array(1,4))) <console>:9: error: type mismatch; found : Seq[Array[Int]] required: Seq[Seq[?]] f(Seq(Array(1,4))) ^ (失败)对于didierd的想法的REPL 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)可能并不是那么糟糕. 解决方法
好吧,最后得到的东西干净简单,不需要任何新的暗示,虽然这样做效率低,因为它从数组转换为Seq只是为了它可以再转换回来.或者你可以使用一个隐含的数组:
隐含的免费答案: def ss2aa[A,B[_],C[_]](c: C[B[A]])( implicit b2seq: B[A] => Seq[A],c2seq: C[B[A]] => Seq[B[A]],ma: ClassManifest[A] ) = c2seq(c).map(b => b2seq(b).toArray).toArray 效率更高,隐含: implicit def seq2array[A: ClassManifest](sa: Seq[A]) = sa.toArray def ss2aa[A,C[_]](c: C[B[A]])( implicit b2arr: B[A] => Array[A],c2arr: C[B[A]] => Array[B[A]],ma: ClassManifest[A] ) = c2arr(c).map(b2arr) 更老,更笨拙,但可能更有效的答案: 为了正常工作,这显然需要一个相当重要的解决方案.一种方法是使用Either编码Array和Seq的类型联合: implicit def ss2leftleft[A](ssa: Seq[Seq[A]]) = Left(Left(ssa)) implicit def sa2leftright[A](saa: Seq[Array[A]]) = Left(Right(saa)) implicit def as2rightleft[A](asa: Array[Seq[A]]) = Right(Left(asa)) implicit def aa2rightright[A](aaa: Array[Array[A]]) = Right(Right(aaa)) def ss2aa[A: Manifest]( x: Either[Either[Seq[Seq[A]],Seq[Array[A]]],Either[Array[Seq[A]],Array[Array[A]]]] ) = x match { case Left(Left(y)) => y.map(_.toArray).toArray case Left(Right(y)) => y.toArray case Right(Left(y)) => y.map(_.toArray) case Right(Right(y)) => y } 如果你觉得这样,你当然可以定义你自己的超类和子类包装器做同样的事情.可能比使用Either更安全. 另一个选择是使用Miles Sabin’s type union operator.通过清单工作有点难看;这是一个实际上安全的版本,但编译器不知道它,因此需要进行强制转换: object Example { // Type union system from Miles Sabin (with non-Unicode names) type Not[A] = A => Nothing type Union[A,B] = Not[Not[A] with Not[B]] type Id[A] = Not[Not[A]] def ss2aa[A,C[_]](b: C[B[A]])( implicit ev: (Id[B[A]] <:< Union[Seq[A],Array[A]]),ev2: (Id[C[B[_]]] <:< Union[Seq[B[_]],Array[B[_]]]),ma: ClassManifest[A],mssa: ClassManifest[Seq[Seq[A]]],msaa: ClassManifest[Seq[Array[A]]],masa: ClassManifest[Array[Seq[A]]],mf: ClassManifest[C[B[A]]] ) = { if (mf <:< mssa) b.asInstanceOf[Seq[Seq[A]]].map(_.toArray).toArray else if (mf <:< masa) b.asInstanceOf[Array[Seq[A]]].map(_.toArray) else if (mf <:< msaa) b.asInstanceOf[Seq[Array[A]]].toArray else b.asInstanceOf[Array[Array[A]]] } } 总的来说,我会说第一个解决方案有点清洁. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |