Scala中迭代器的map与flatMap有何区别?

60

Iterablemap函数和flatMap函数有什么区别?

5个回答

58

以上内容都是真实的,但还有一件非常方便的事情: flatMap 将一个 List[Option[A]] 转换为 List[A],并移除所有深入到 NoneOption。这对于超越使用 null 是一个关键的概念突破。


3
哦,这是关于Option的另一个好技巧,我从未想过。我只是让方法返回一个包含1个或多个元素的列表,并没有看到Option.toList方法:List( Some( "foo" ), None, Some( "bar" ) ).flatMap( _.toList ) - Tristan Juricek
或者更好的方法是,使用Tristan的方法和Option.toIterator,这样你就不必在不必要的情况下遍历整个列表。 - Jonathan Schneider

45

这里有一个相当不错的解释:

http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-2

以列表为例:

Map 的签名如下:

map [B](f : (A) => B) : List[B]

flatMap的用途是

flatMap [B](f : (A) => Iterable[B]) : List[B]

所以,flatMap接受类型[A]并返回可迭代类型[B],而map接受类型[A]并返回类型[B]。

这也将给你一个想法,即flatMap将“展平”列表。

val l  = List(List(1,2,3), List(2,3,4))

println(l.map(_.toString)) // changes type from list to string
// prints List(List(1, 2, 3), List(2, 3, 4))

println(l.flatMap(x => x)) // "changes" type list to iterable
// prints List(1, 2, 3, 2, 3, 4)

13
有趣的是,根据单子公理,l flatMap { x => x }l.flatten完全等效。flatMap是Scala中单子绑定操作(在Haskell中为>>=)的等价物。我发现它在非集合的单子上最有用,比如Option。与集合一起使用时,它最常用于实现“嵌套映射循环”,返回一个集合作为结果。 - Daniel Spiewak
说得好。与一堆语句(如if(x != null and x.foo != null))相比,选项的链接更易于使用。http://blog.lostlake.org/index.php?/archives/50-The-Scala-Option-class-and-how-lift-uses-it.html详细讨论了这个问题。 - agilefall
1
println(l.flatMap(x => x)) 这个不再起作用了,需要像这样使用 flatMap:http://aperiodic.net/phil/scala/s-99/p07.scala - Olivier Girardot

8
lines.map(line => line split "\\W+") // will return a list of arrays of words
lines.flatMap(line => line split "\\W+") // will return a list of words

你可以在for循环中更好地理解这个:

for {line <- lines
     word <- line split "\\W+"}
yield word.length

这意味着:

lines.flatMap(line => line.split("\\W+").map(word => word.length))

每个for循环中的迭代器都会被转换为“flatMap”,除了最后一个迭代器,它会被转换为“map”。这样,不会返回嵌套的集合(例如列表中包含数组或缓冲区等),而是返回一个平坦的集合。在这种情况下,由yield生成的元素组成了一个列表,其中包含整数。


8

来自scaladoc:

  • map

将给定的函数f应用于此可迭代对象的每个元素,并返回结果可迭代对象。

  • flatMap

将给定的函数f应用于此可迭代对象的每个元素,然后连接结果。


我需要更多的分析/解释。 - Landon Kuhn
好的,那么请将您的问题更具体化。说明您已经知道什么,以及您需要澄清的内容。 - skaffman
5
我更喜欢你那句尖酸刻薄的评论。 - Landon Kuhn
我也是,但我想谨慎比勇气更重要 :) - skaffman

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接