【问题标题】:Converting from List[Vector[T]] to Vector[List[T]] in a generic way以通用方式从 List[Vector[T]] 转换为 Vector[List[T]]
【发布时间】:2011-03-08 01:51:51
【问题描述】:

我想知道是否可以将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 上下文绑定可以完全单独使用。

【问题讨论】:

    标签: scala scala-collections


    【解决方案1】:

    我们在 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))
    

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

    见证了这一点

    【讨论】:

    • CanBuildAnySelf 基本上是大约 10 行代码,它就像一个魅力。非常令人印象深刻。
    • 别看asInstanceOf
    【解决方案2】:

    这行得通:

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

    【讨论】:

    • 我正在寻找一个函数,该函数将以通用方式对不同类型执行相同的操作。
    猜你喜欢
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    相关资源
    最近更新 更多