【发布时间】:2010-11-06 18:47:45
【问题描述】:
Iterable的map和flatMap函数有什么区别?
【问题讨论】:
标签: scala monads scala-collections
Iterable的map和flatMap函数有什么区别?
【问题讨论】:
标签: scala monads scala-collections
以上都是正确的,但还有一件事很方便:flatMap 将List[Option[A]] 转换为List[A],删除任何向下钻取到None 的Option。这是超越使用null 的关键概念突破。
【讨论】:
Option.toList 方法: List( Some( "foo" ), None, Some( "bar" ) ).flatMap( _.toList )
Option.toIterator 与 Tristan 的方法一起使用,这样您就不会在必要时遍历整个列表。
这里有一个很好的解释:
http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-2
以列表为例:
地图的签名是:
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)
【讨论】:
l flatMap { x => x }精确等同于l.flatten。 FlatMap 相当于 Scala 的一元 bind 操作(在 Haskell 中为 >>=)。我发现它对诸如 Option 之类的非集合单子最有用。当与集合结合使用时,它对于实现“嵌套映射循环”最为有用,并返回一个集合作为结果。
【讨论】:
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 {line <- lines
word <- line split "\\W+"}
yield word.length
这翻译成:
lines.flatMap(line => line.split("\\W+").map(word => word.length))
for 中的每个迭代器都将被翻译成“flatMap”,除了最后一个被翻译成“map”的迭代器。这样,您不会返回嵌套集合(blah、blah、blah 缓冲区的数组列表),而是返回一个平面集合。由正在生成的元素形成的集合——在本例中为整数列表。
【讨论】:
看这里: http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-2
“搜索 flatMap”——那里有一个很好的解释。 (基本上它是“扁平化”和“地图”的组合——来自其他语言的特征)。
【讨论】: