example - ¿Cómo puedo convertir fácilmente de un tipo de colección a otro durante un filtro, mapa, flatMap en Scala?
java flat (1)
Supongamos que tengo una List[Int]
y quiero llamar a toString
en cada elemento y obtener el resultado como Vector[String]
.
¿Cuáles son las diversas formas de hacer esto en Scala? ¿Hay una solución con una cantidad mínima de tipeo explícito? - es decir, quiero especificar que quiero un Vector
lugar de una List
, pero me gustaría que el argumento String
se infiera de la función de filtro.
¿O debería pasar explícitamente una instancia de CanBuildFrom
? ¿De dónde los obtengo - para Seq
s, Set
sy Map
s?
Usando BreakOut
Use breakOut
como CanBuildFrom
y deje que el tipeador sepa cuál es su tipo de resultado (desafortunadamente debe especificar Cadena aquí)
scala> import collection.breakOut
import collection.breakOut
scala> List(1, 2, 3)
res0: List[Int] = List(1, 2, 3)
scala> res0.map(_.toString)(breakOut) : Vector[String]
res2: Vector[String] = Vector(1, 2, 3)
Uso de [Colección] (comenzando con Scala 2.10.0)
Scala 2.10.0 introdujo una forma fácil de convertir una colección a otra colección:
scala> List(1, 2, 3).map(_.toString).to[Vector]
res0: Vector[String] = Vector(1, 2, 3)
Usando toIndexedSeq
Alternativamente, solicite un IndexedSeq
explícitamente:
scala> res0.map(_.toString).toIndexedSeq
res4: scala.collection.immutable.IndexedSeq[String] = Vector(1, 2, 3)
Si quiere hacer esto sin crear la List
intermedia, entonces:
scala> res0.view.map(_.toString).toIndexedSeq
res5: scala.collection.immutable.IndexedSeq[String] = Vector(1, 2, 3)
Usando transformaciones naturales
Podrías hacerlo (torpemente, pero de manera más general) usando transformaciones naturales
scala> trait Trans[F[_], G[_]] {
| def f2g[A](f : F[A]) : G[A]
| }
defined trait Trans
Ahora proporcione una instancia de clase de clase de la transformación List ~> Vector:
scala> implicit val List2Vector = new Trans[List, collection.immutable.Vector] {
| def f2g[A](l : List[A]) : Vector[A] = l.map(identity[A])(collection.breakOut)
| }
List2Vector: java.lang.Object with Trans[List,scala.collection.immutable.Vector] = $anon$1@56329755
Definir un contenedor y una conversión implícita:
scala> class Clever[M[_], A](ma : M[A]) { def to[N[_]](implicit t : Trans[M, N]) : N[A] = t.f2g(ma) }
defined class Clever
scala> implicit def ma2clever[M[_], A](ma : M[A]) = new Clever[M, A](ma)
ma2clever: [M[_],A](ma: M[A])Clever[M,A]
Entonces:
scala> List(1, 2, 3).map(_.toString).to[Vector]
res4: Vector[java.lang.String] = Vector(1, 2, 3)