Vin*_*ele 6 functional-programming scala
我是函数式编程的新手,因此使用函数式方法解决一些问题似乎更难.
假设我有一个数字列表,例如1到10.000,我想得到列表中最多总数为n的项目(假设为100).因此,它会得到数字,直到它们的总和大于100.
在命令式编程中,解决这个问题是微不足道的,因为我可以在每次交互中保留一个变量,并在达到目标后停止.
但是我怎么能在函数式编程中做同样的事情呢?由于sum函数在已完成的列表上运行,而我仍然没有完成的列表,我怎样才能"继续"计算?
如果sum是懒惰计算的,我可以这样写:
(1 to 10000).sum.takeWhile(_ < 100)
Run Code Online (Sandbox Code Playgroud)
PS:即使任何答案都会受到赞赏,我也希望每次都能计算出一个总和,因为显然命令式版本在速度方面会更加优化.
编辑:
我知道我可以将命令式循环方法"转换"为功能递归函数.我更感兴趣的是找到一个现有的库函数是否可以为我提供一种方法,让我不需要每次需要时都写一个.
使用Stream.
scala> val ss = Stream.from(1).take(10000)
ss: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> ss.scanLeft(0)(_ + _)
res60: scala.collection.immutable.Stream[Int] = Stream(0, ?)
scala> res60.takeWhile(_ < 100).last
res61: Int = 91
Run Code Online (Sandbox Code Playgroud)
编辑:
获取组件也不是很棘手.这是你如何做到的:
scala> ss.scanLeft((0, Vector.empty[Int])) { case ((sum, compo), cur) => (sum + cur, compo :+ cur) }
res62: scala.collection.immutable.Stream[(Int, scala.collection.immutable.Vector[Int])] = Stream((0,Vector()), ?)
scala> res62.takeWhile(_._1 < 100).last
res63: (Int, scala.collection.immutable.Vector[Int]) = (91,Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13))
Run Code Online (Sandbox Code Playgroud)
元组的第二部分是你想要的结果.
显而易见,在这种情况下,构建向量是浪费的.相反,我们只能存储有助于求和的流中的最后一个数字.
scala> ss.scanLeft(0)(_ + _).zipWithIndex
res64: scala.collection.immutable.Stream[(Int, Int)] = Stream((0,0), ?)
scala> res64.takeWhile(_._1 < 100).last._2
res65: Int = 13
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
737 次 |
| 最近记录: |