以通用方式从List [Vector [T]]转换为Vector [List [T]]

时间:2011-03-06 21:51:45

标签: scala scala-collections

我正在试图弄清楚我是否可以通用方式将List(Vector(1), Vector(2,3))转换为Vector(List(1), List(2,3))或任何两个可遍历的类。

这是我到目前为止所做的:

import collection.generic.CanBuildFrom
import collection.breakOut
import collection.mutable.ListBuffer

def f[A, CC[X] <: Traversable[X], DD[Y] <: Traversable[Y]](outer: DD[CC[A]])
  (implicit cbf1: CanBuildFrom[Traversable[_], A, DD[A]],
  cbf2: CanBuildFrom[Traversable[_], DD[A], CC[DD[A]]])
  : CC[DD[A]] = {
  val builder2 = cbf2()
  outer.foreach { inner =>
    val builder1 = cbf1()
    builder1 ++= inner
    builder2 += builder1.result
  }
  builder2.result
}

f(Vector(List(1), List(2,3)))(breakOut, breakOut) 
f(ListBuffer(Vector(1), Vector(2,3)))(breakOut, breakOut) 

如果我删除了breakOuts,它将无法编译:

f(Vector(List(1), List(2,3))) // won't work

找不到参数cbf1的隐含值:scala.collection.generic.CanBuildFrom [Traversable [_],Int,scala.collection.immutable.Vector [Int]]

我可以导入隐含的内容吗?任何其他方法来解决这个问题,不需要breakOuts?


根据反义词的答案进行编辑:

import scalaz.CanBuildAnySelf
def f[A, CC[X] <: Traversable[X] : CanBuildAnySelf, 
         DD[Y] <: Traversable[Y] : CanBuildAnySelf](outer: DD[CC[A]])
           : CC[DD[A]] = {
  val builder2 = implicitly[CanBuildAnySelf[CC]].builder[DD[A], DD[A]].apply()
  outer.foreach { inner =>
    val builder1 = implicitly[CanBuildAnySelf[DD]].builder[A, A].apply()
    builder1 ++= inner
    builder2 += builder1.result
  }
  builder2.result
}

看到CanBuildAnySelf上下文绑定可以完全单独使用,真是令人印象深刻。

2 个答案:

答案 0 :(得分:5)

我们在Scalaz中完成它,所以它当然是可能的。

scala> import scalaz._
import scalaz._

scala> import Scalaz._
import Scalaz._

scala> List(Vector(1, 2, 3)).sequence
res1: scala.collection.immutable.Vector[List[Int]] = Vector(List(1, 2, 3), List(1, 2, 3), List(1, 2, 3))

scala> Seq(List(1), List(3)).sequence
res2: List[Seq[Int]] = List(List(1, 3))

scala> Vector(ArraySeq(1, 2, 3)).sequence
res3: scala.collection.mutable.ArraySeq[scala.collection.immutable.Vector[Int]] = ArraySeq(Vector(1, 2, 3), Vector(1, 2, 3), Vector(1, 2, 3))

我们只考虑表现良好的&#39;集合,即可以包含任意元素类型的集合,与BitSet不同。这与https://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/CanBuildAnySelf.scala

见证

答案 1 :(得分:0)

这有效:

val l = List(Vector(1), Vector(2, 3))
val v = Vector((for (v <- l) yield v.toList): _*)