If I use xxx.flatMap(_.split(" "))
, will it split the array an then flatten or will it flatten and then split?
The purpose of flatmap
functions is to take a function that returns a list, and then flatten the result.
So it will map the iterable (which splits in this case), then flatten the resulting 2D iterable (List in this case).
Let's expand things a bit. First, let's define your xxx
with examples of the sort that I think you intend:
val xxx = Array("hello there 马慧超", "how are you", "nice to meet you")
Now, let's write out your logic longer hand:
def words( str : String ) : Array[String] = str.split(" ")
xxx.flatMap( string => words(string) )
We start with an array of Strings. At some intermediate point, the function words
is called on each of those immediate Strings, which yields Array[String]
, so conceptually we have a sequence of Arrays of String.
But we end up with just an array of Strings, "flattened" in that each of the words in the intermediate sequence of word arrays becomes part of one long array.
So, conceptually, first we execute that mapping function (words
, or more directly split
in this case), and then we flatten.
So, to answer your question directly, split then flatten.
Update (More, 'cuz why not?)
It's not even clear what it would mean to "flatten" a sequence of Strings, but informally you might imagine concatenation first. We can easily prove this is not what happens by instrumenting. If you try
def words( str : String ) : Array[String] = {println(str); str.split(" ")}
xxx.flatMap( string => words(string) )
you will see all of the individual Strings, not one concatenated String.
This is logically necessary for other types with flatMap
methods. For
Some("there").flatMap( str => Some( str.toUpperCase ) )
there is no "flattening" you could perform on the Option Some(there)
on which flatMap is called. "flattening" is only defined and meaningful once we have nested monadic contexts, i.e. when thinking about a hypothetical intermediate Some(Some(THERE))
value on which a flatten
method would get called to produce Some(THERE)
.
Many good answers, but all are way too long :) It's very simple: before you split, there is nothing to flatten.
flatMap is a combination of map and then flatten. Example below can explain the process where we are calling map and then flatten and the result is a List[Char], while flatMap directly converts the Seq to List[Char].
val avengers = Seq("Ironman", "Thor", "Captain America")
val capsAvengers = avengers.map(_.toUpperCase)
println(avengers)
println(capsAvengers)
println(capsAvengers.flatten)
println(avengers.flatMap(.toUpperCase))
result:
List(Ironman, Thor, Captain America)
List(IRONMAN, THOR, CAPTAIN AMERICA)
List(I,R,O,N,M,A,N,T,H,O,R,C,A,P,T,A,I,N, ,A,M,E,R,I,C,A)
List(I,R,O,N,M,A,N,T,H,O,R,C,A,P,T,A,I,N, ,A,M,E,R,I,C,A)
The flatMap can be saw as the combination of operation 'map' and 'flatten'.
As for your question, the answer is 'split' first and then 'flatten'.
The following example is use to illustrate this:
val nestedNumbers = List(List(1, 2), List(3, 4))
nestedNumbers.flatMap(x => x.map(_ * 2))
the output is
res0: List[Int] = List(2, 4, 6, 8)
, which is equivalent to the following code:
nestedNumbers.map((x: List[Int]) => x.map(_ * 2)).flatten
,its output is also
res0: List[Int] = List(2, 4, 6, 8)
the reference is there https://twitter.github.io/scala_school/zh_cn/collections.html#flatMap
have a good luck
© 2022 - 2024 — McMap. All rights reserved.