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

问题描述 投票:7回答:3
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)

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

scala functional-programming flatmap
3个回答
9
投票

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

map(identity)为您提供相同的集合,所以最后它只与flatten相同。

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


5
投票

从概念上讲,结果没有区别...... flatMap花费更多的时间来产生相同的结果......

I will show it more practically with an example of flatMap, map & then flatten and flatten

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在重复几次后执行相同的结果

Conclusion : flatten is efficient

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)

3
投票

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

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

当你需要做一个flatMap(除了map以外的函数)后立即使用identity,你会使用flatten

© www.soinside.com 2019 - 2024. All rights reserved.