Is there any method that does the same as map () but creates a different type of container?

Sometimes I need to create a collection by mapping another to a different type. For example, some function requires List[_]

as its parameter type, but I need to create this by matching a IndexedSeq[_]

:

val r = (1 to n).map { ... }
someFunction(r.toList)

      

While I can accomplish this by calling a method IndexedSeq[_]

map

and then another call toList

, this creates a redundant intermediate collection. Is there a way to avoid this redundant step while keeping the code concise?

+3


source to share


3 answers


View full signature for map

:

def map[B, That](f: (A) ⇒ B)(implicit bf: CanBuildFrom[List[A], B, That]): That

      

The key to this is implicit CanBuildFrom

, which determines how the result collection is created from the input collection. We can replace the implicit one CanBuildFrom

with an explicit one, which allows us to build a different collection of results.

Better yet, we don't even need to write this explicit method! He's already there, in uniform scala.collection.breakOut

. From ScalaDoc:



Provides a CanBuildFrom instance that creates a specific target collection (To) regardless of the source collection (From).

So, if we go to collection.breakOut

, we can specify exactly what we want with the method map

:

val x = IndexedSeq(1,2,3,4,5)
x.map[Int, List[Int]](_ * 2)(collection.breakOut)
> res6: List[Int] = List(2, 4, 6, 8, 10) 

      

+9


source


The answer to your question collection.breakOut

is as pointed out by om-nom-nom in his comment.

breakOut

- an additional argument provided to the method map

and - to keep it simple - it allows you to return different collection types from map

:

def directMapExample(seq: Seq[Int]): Set[Int] = seq.map(_ * 2)(collection.breakOut)

      



Please note that the following fails when compiled:

def directMapExample2(seq: Seq[Int]): Set[Int] = seq.map(_ * 2)

      

See fooobar.com/questions/1413 / ... for details .

+3


source


Can using a view help?

val r = (1 to n).view.map { … }
someFunction(r.toList)

      

The function map

is a strict transformer on Range

. However, if you first include it in the view, then Range

(which is a lax collection) will be wrapped inside an object that is loosely implemented map

. The full range of values ​​will only be generated when called toList

.

0


source







All Articles