在 flatMap、flatten 或 map 中哪个先发生?
Which happens first in flatMap, flatten or map?
如果我使用 xxx.flatMap(_.split(" "))
,它会拆分数组然后展平还是展平然后拆分?
flatmap
函数的目的是获取一个 returns 列表的函数,然后将结果展平。
因此它将映射可迭代对象(在本例中为拆分),然后展平生成的 2D 可迭代对象(在本例中为列表)。
让我们扩展一下。首先,让我们用我认为您想要的那种示例来定义您的 xxx
:
val xxx = Array("hello there 马慧超", "how are you", "nice to meet you")
现在,让我们用更长的时间写出你的逻辑:
def words( str : String ) : Array[String] = str.split(" ")
xxx.flatMap( string => words(string) )
我们从一个字符串数组开始。在某个中间点,对每个直接字符串调用函数 words
,这会产生 Array[String]
,因此从概念上讲,我们有一个字符串数组序列。
但我们最终得到的只是一个字符串数组,"flattened" 因为单词数组中间序列中的每个单词都成为一个长数组的一部分。
因此,从概念上讲,我们首先执行该映射函数(words
,或者更直接地 split
在这种情况下),然后我们展平。
所以,直接回答你的问题,拆分然后展平。
更新(更多,为什么不呢?)
甚至不清楚 "flatten" 字符串序列的含义,但非正式地,您可能首先想到串联。我们可以很容易地证明这不是通过检测发生的情况。如果你尝试
def words( str : String ) : Array[String] = {println(str); str.split(" ")}
xxx.flatMap( string => words(string) )
您将看到所有单独的字符串,而不是一个串联的字符串。
这对于具有 flatMap
方法的其他类型在逻辑上是必要的。对于
Some("there").flatMap( str => Some( str.toUpperCase ) )
没有 "flattening" 您可以在调用 flatMap 的选项 Some(there)
上执行。 "flattening" 只有在我们拥有嵌套的 monadic 上下文时才定义和有意义,即当考虑一个假设的中间 Some(Some(THERE))
值时,flatten
方法将被调用以产生 Some(THERE)
。
flatMap可以看作是操作'map'和'flatten'的组合。
关于你的问题,答案是先'split'再'flatten'。
下面的例子就是用来说明这一点的:
val nestedNumbers = List(List(1, 2), List(3, 4))
nestedNumbers.flatMap(x => x.map(_ * 2))
输出是
res0: List[Int] = List(2, 4, 6, 8)
,相当于下面的代码:
nestedNumbers.map((x: List[Int]) => x.map(_ * 2)).flatten
,它的输出也是
res0: List[Int] = List(2, 4, 6, 8)
有参考资料
https://twitter.github.io/scala_school/zh_cn/collections.html#flatMap
祝你好运
flatMap是把map组合起来然后flatten。下面的例子可以解释我们调用map然后flatten结果是List[Char]的过程,而flatMap直接将Seq转换为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))
结果:
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)
很多好的答案,但都太长了:)
很简单:在你分裂之前,没有什么可以压平的。
如果我使用 xxx.flatMap(_.split(" "))
,它会拆分数组然后展平还是展平然后拆分?
flatmap
函数的目的是获取一个 returns 列表的函数,然后将结果展平。
因此它将映射可迭代对象(在本例中为拆分),然后展平生成的 2D 可迭代对象(在本例中为列表)。
让我们扩展一下。首先,让我们用我认为您想要的那种示例来定义您的 xxx
:
val xxx = Array("hello there 马慧超", "how are you", "nice to meet you")
现在,让我们用更长的时间写出你的逻辑:
def words( str : String ) : Array[String] = str.split(" ")
xxx.flatMap( string => words(string) )
我们从一个字符串数组开始。在某个中间点,对每个直接字符串调用函数 words
,这会产生 Array[String]
,因此从概念上讲,我们有一个字符串数组序列。
但我们最终得到的只是一个字符串数组,"flattened" 因为单词数组中间序列中的每个单词都成为一个长数组的一部分。
因此,从概念上讲,我们首先执行该映射函数(words
,或者更直接地 split
在这种情况下),然后我们展平。
所以,直接回答你的问题,拆分然后展平。
更新(更多,为什么不呢?)
甚至不清楚 "flatten" 字符串序列的含义,但非正式地,您可能首先想到串联。我们可以很容易地证明这不是通过检测发生的情况。如果你尝试
def words( str : String ) : Array[String] = {println(str); str.split(" ")}
xxx.flatMap( string => words(string) )
您将看到所有单独的字符串,而不是一个串联的字符串。
这对于具有 flatMap
方法的其他类型在逻辑上是必要的。对于
Some("there").flatMap( str => Some( str.toUpperCase ) )
没有 "flattening" 您可以在调用 flatMap 的选项 Some(there)
上执行。 "flattening" 只有在我们拥有嵌套的 monadic 上下文时才定义和有意义,即当考虑一个假设的中间 Some(Some(THERE))
值时,flatten
方法将被调用以产生 Some(THERE)
。
flatMap可以看作是操作'map'和'flatten'的组合。
关于你的问题,答案是先'split'再'flatten'。
下面的例子就是用来说明这一点的:
val nestedNumbers = List(List(1, 2), List(3, 4))
nestedNumbers.flatMap(x => x.map(_ * 2))
输出是
res0: List[Int] = List(2, 4, 6, 8)
,相当于下面的代码:
nestedNumbers.map((x: List[Int]) => x.map(_ * 2)).flatten
,它的输出也是
res0: List[Int] = List(2, 4, 6, 8)
有参考资料 https://twitter.github.io/scala_school/zh_cn/collections.html#flatMap
祝你好运
flatMap是把map组合起来然后flatten。下面的例子可以解释我们调用map然后flatten结果是List[Char]的过程,而flatMap直接将Seq转换为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))
结果:
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)
很多好的答案,但都太长了:) 很简单:在你分裂之前,没有什么可以压平的。