Jak łatwo konwertować z jednego typu kolekcji na inny podczas filtrowania, mapy, flatmapy w Scali?

Załóżmy, że mam List[Int] i chcę wywołać {[1] } na każdym elemencie i odzyskać wynik jako Vector[String].

Jakie są różne sposoby, aby to zrobić w Scali? Czy istnieje rozwiązanie z minimalną ilością jawnego pisania? - tzn. chcę określić, że chcę Vector zamiast List, ale chciałbym, aby argument String został wywnioskowany z funkcji filtra.

Czy powinienem jawnie przekazać CanBuildFrom instancję? Skąd je wziąć-dla Seq s, Set S I Map s?

Author: Jean-Philippe Pellet, 2011-04-08

1 answers

Używanie breakOut

Użyj breakOut jako CanBuildFrom i daj typerowi znać, jaki ma być Typ wyniku (niestety musisz podać tutaj ciąg znaków)

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)

Using to [Collection] (starting with Scala 2.10.0)

Scala 2.10.0 wprowadziła łatwy sposób konwersji kolekcji na inną kolekcję:

scala> List(1, 2, 3).map(_.toString).to[Vector]
res0: Vector[String] = Vector(1, 2, 3)

Using toIndexedSeq

Alternatywnie poproś o IndexedSeq jawnie:

scala> res0.map(_.toString).toIndexedSeq
res4: scala.collection.immutable.IndexedSeq[String] = Vector(1, 2, 3)

Jeśli chcesz to zrobić bez tworzenie pośredniego List, następnie:

scala> res0.view.map(_.toString).toIndexedSeq
res5: scala.collection.immutable.IndexedSeq[String] = Vector(1, 2, 3)

Wykorzystanie Naturalnych Przekształceń

Można to zrobić (niezręcznie, ale ogólniej) używając naturalnych przekształceń

scala> trait Trans[F[_], G[_]] {
 | def f2g[A](f : F[A]) : G[A]
 | }
defined trait Trans

Teraz podaj instancję typeklasy z listy ~ > transformacja wektorowa:

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

Zdefiniuj wrapper i konwersję implicit:

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]

Potem:

scala> List(1, 2, 3).map(_.toString).to[Vector]
res4: Vector[java.lang.String] = Vector(1, 2, 3)
 52
Author: oxbow_lakes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-17 15:24:09