zig*_*tar 5 scala type-conversion scala-collections
正如标题所述,我希望有一种方法可以应用于任何类型的参数,如Array[Array[_]]or Seq[Array[_]]或Array[Seq[_]]or 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)))
}
Run Code Online (Sandbox Code Playgroud)
本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)))
Run Code Online (Sandbox Code Playgroud)
为了完整性,这里是构造函数; 也许它很重要,因为它需要一个Manifest对A.
class CombinationIterator[A: Manifest](components: Array[Array[A]]) extends Iterator[Array[A]]
Run Code Online (Sandbox Code Playgroud)
以下适用于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, 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)))
^
Run Code Online (Sandbox Code Playgroud)
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)))
^
Run Code Online (Sandbox Code Playgroud)
以下代码适用于我的项目.也许并非涵盖所有特殊情况.这是雷克斯的第二个答案的变体.
我觉得暗示很好地包含在伴侣对象中.
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)
}
}
Run Code Online (Sandbox Code Playgroud)
发布一些关于问题背后原因的新见解.由于性能原因,我想拥有这些嵌套数组.但是数组对于原始类型更重要.因此,从性能角度来看,将外部数组作为"适当的"数据结构(如a)可能并不是那么糟糕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
Run Code Online (Sandbox Code Playgroud)
implicit def seq2array[A: ClassManifest](sa: Seq[A]) = sa.toArray
def ss2aa[A,B[_],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)
Run Code Online (Sandbox Code Playgroud)
为了正常工作,这显然需要一个相当重量级的解决方案。一种方法是使用Array和 的类型并集进行编码:SeqEither
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
}
Run Code Online (Sandbox Code Playgroud)
如果您愿意,您当然可以定义自己的超类和子类包装器来执行相同的操作。可能比使用更安全Either。
另一种选择是使用Miles Sabin 的类型 union 运算符。处理清单有点难看;这是一个实际上安全的版本,但编译器不知道它,因此需要进行强制转换:
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,B[_],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]]]
}
}
Run Code Online (Sandbox Code Playgroud)
总的来说,我想说第一个解决方案更干净一些。
| 归档时间: |
|
| 查看次数: |
326 次 |
| 最近记录: |