flatten和flatMap(身份)之间有什么区别吗?

时间:2014-11-18 22:14:17

标签: scala functional-programming flatmap

scala> List(List(1), List(2), List(3), List(4))
res18: List[List[Int]] = List(List(1), List(2), List(3), List(4))

scala> res18.flatten
res19: List[Int] = List(1, 2, 3, 4)

scala> res18.flatMap(identity)
res20: List[Int] = List(1, 2, 3, 4)

这两个功能有什么区别吗?何时使用一个而不是另一个?有任何权衡吗?

3 个答案:

答案 0 :(得分:9)

您可以将flatMap(identity)视为map(identity).flatten。 (当然它没有这样实现,因为它需要两次迭代)。

map(identity)为您提供相同的集合,因此最终只与flatten相同。

我个人会坚持flatten,因为它更短/更容易理解和设计来完全做到这一点。

答案 1 :(得分:5)

  

从概念上讲,结果没有差异...... flatMap正在采取行动   有更多的时间来产生相同的结果...

我将以flatMapmap&的示例更实际地展示它。然后是flattenflatten

object Test extends App {
  // flatmap
  println(timeElapsed(List(List(1, 2, 3, 4), List(5, 6, 7, 8)).flatMap(identity)))
  // map and then flatten
  println(timeElapsed(List(List(1, 2, 3, 4), List(5, 6, 7, 8)).map(identity).flatten))
  // flatten
  println(timeElapsed(List(List(1, 2, 3, 4), List(5, 6, 7, 8)).flatten))

  /**
   * timeElapsed
   */
  def timeElapsed[T](block: => T): T = {
    val start = System.nanoTime()
    val res = block
    val totalTime = System.nanoTime - start
    println("Elapsed time: %1d nano seconds".format(totalTime))
    res
  }
}

重复多次后,flatMapflatten执行的结果相同

结论:flatten效率很高

Elapsed time: 2915949 nano seconds
List(1, 2, 3, 4, 5, 6, 7, 8)
Elapsed time: 1060826 nano seconds
List(1, 2, 3, 4, 5, 6, 7, 8)
Elapsed time: 81172 nano seconds
List(1, 2, 3, 4, 5, 6, 7, 8)

答案 2 :(得分:3)

从概念上讲,没有区别。实际上,flatten更有效率,并传达了更清晰的意图。

通常,您不能直接使用identity。它更像是作为参数传入或被设置为默认值的情况。编译器可以对其进行优化,但是你要为每个元素冒一个多余的函数调用。

当您需要flatMapmap以外的功能)后紧跟identity时,您可以使用flatten