Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala collections: transform content and type of the collection in one pass

I am looking for a way to efficiently transform content and type of the collection.

For example apply map to a Set and get result as List.

Note that I want to build result collection while applying transformation to source collection (i.e. without creating intermediate collection and then transforming it to desired type).

So far I've come up with this (for Set being transformed into List while incrementing every element of the set):

val set = Set(1, 2, 3)

val cbf = new CanBuildFrom[Set[Int], Int, List[Int]] {
    def apply(from: Set[Int]): Builder[Int, List[Int]] = List.newBuilder[Int]
    def apply(): Builder[Int, List[Int]] = List.newBuilder[Int]
}

val list: List[Int] = set.map(_ + 1)(cbf)

... but I feel like there should be more short and elegant way to do this (without manually implementing CanBuildFrom every time when I need to do this).

Any ideas how to do this?

like image 645
Eugene Loy Avatar asked Jun 09 '14 16:06

Eugene Loy


2 Answers

This is exactly what scala.collection.breakOut is for—it'll conjure up the CanBuildFrom you need if you tell it the desired new collection type:

import scala.collection.breakOut

val xs: List[Int] = Set(1, 2, 3).map(_ + 1)(breakOut)

This will only traverse the collection once. See this answer for more detail.

like image 91
Travis Brown Avatar answered Oct 13 '22 16:10

Travis Brown


I think that this might do what you want, though I am not 100% positive so maybe someone could confirm:

(Set(1, 2, 3).view map (_ + 1)).toList

view creates, in this case, an IterableView, which, when you call map on it, does not actually perform the mapping. When toList is called, the map is performed and a list is built with the results.

like image 26
Owen Avatar answered Oct 13 '22 14:10

Owen