首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala中的无限流

Scala中的无限流
EN

Stack Overflow用户
提问于 2011-06-20 15:47:00
回答 5查看 31.3K关注 0票数 49

假设我有一个函数,例如,旧的最爱

代码语言:javascript
复制
def factorial(n:Int) = (BigInt(1) /: (1 to n)) (_*_)

现在我想找出factorial(n)适合长整型的n的最大值。我能做到

代码语言:javascript
复制
(1 to 100) takeWhile (factorial(_) <= Long.MaxValue) last

这是可行的,但100是一个任意的大数字;我真正想要的是左侧的无限流,它会不断生成更高的数字,直到满足takeWhile条件。

我想出了一个

代码语言:javascript
复制
val s = Stream.continually(1).zipWithIndex.map(p => p._1 + p._2)

但是有没有更好的方法呢?

(我也知道我可以递归地得到一个解决方案,但这不是我想要的。)

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-06-20 15:55:07

代码语言:javascript
复制
Stream.from(1)

创建一个从1开始并以1递增的流。它都在API docs中。

票数 128
EN

Stack Overflow用户

发布于 2011-06-20 16:53:29

使用迭代器的解决方案

您也可以使用Iterator而不是StreamStream保留所有计算值的引用。因此,如果您计划只访问每个值一次,迭代器是一种更有效的方法。不过,迭代器的缺点是它的可变性。

有一些很好的方法可以方便地创建在其companion object上定义的Iterator

编辑

不幸的是,据我所知,没有短的(库支持的)方法来实现像这样的事情

代码语言:javascript
复制
Stream.from(1) takeWhile (factorial(_) <= Long.MaxValue) last

对于一定数量的元素,我采用drop(n: Int)dropWhile方法来推进Iterator

代码语言:javascript
复制
Iterator.from(1).dropWhile( factorial(_) <= Long.MaxValue).next - 1

- 1可用于此特殊用途,但不是通用解决方案。但是使用pimp my library在Iterator上实现一个last方法应该没有问题。问题是取无限迭代器的最后一个元素可能是有问题的。因此,它应该作为集成takeWhilelastWith方法来实现。

一种丑陋的解决方法是使用为Iterator实现的sliding

代码语言:javascript
复制
scala> Iterator.from(1).sliding(2).dropWhile(_.tail.head < 10).next.head
res12: Int = 9
票数 31
EN

Stack Overflow用户

发布于 2014-04-25 01:49:18

正如@ziggystar指出的那样,Streams将先前计算的值列表保存在内存中,因此使用Iterator是一个很大的改进。

为了进一步改进答案,我认为“无限流”通常是基于预先计算的值来计算(或可以计算)的。如果是这样的话(在您的factorial流中肯定是这样),我建议使用Iterator.iterate

大致如下所示:

代码语言:javascript
复制
scala> val it = Iterator.iterate((1,BigInt(1))){case (i,f) => (i+1,f*(i+1))}
it: Iterator[(Int, scala.math.BigInt)] = non-empty iterator

然后,您可以执行以下操作:

代码语言:javascript
复制
scala> it.find(_._2 >= Long.MaxValue).map(_._1).get - 1
res0: Int = 22

或者使用@ziggystar sliding解决方案...

脑海中出现的另一个简单的例子是斐波那契数:

代码语言:javascript
复制
scala> val it = Iterator.iterate((1,1)){case (a,b) => (b,a+b)}.map(_._1)
it: Iterator[Int] = non-empty iterator

在这些情况下,你并不是每次都从头开始计算你的新元素,而是为每个新元素做O(1)的工作,这将进一步改善你的运行时间。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6408186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档