Scala中的无限流

Lui*_*hys 43 scala stream

说我有一个功能,例如旧的最爱

def factorial(n:Int) = (BigInt(1) /: (1 to n)) (_*_)
Run Code Online (Sandbox Code Playgroud)

现在,我想找到的最大的价值n为它factorial(n)镶嵌在长.我可以

(1 to 100) takeWhile (factorial(_) <= Long.MaxValue) last
Run Code Online (Sandbox Code Playgroud)

这是有效的,但100是任意大数; 在左侧我真正想要的是一个无限的流,它会一直产生更高的数字,直到满足takeWhile条件.

我想出来了

val s = Stream.continually(1).zipWithIndex.map(p => p._1 + p._2)
Run Code Online (Sandbox Code Playgroud)

但有更好的方法吗?

(我也知道我可以递归地得到一个解决方案,但这不是我正在寻找的.)

Kim*_*bel 120

Stream.from(1)
Run Code Online (Sandbox Code Playgroud)

创建一个从1开始并递增1的流.这些都在API文档中.

  • 自 2.13.0 起,“Stream”已弃用。请改用“LazyList”。所以这将是“LazyList.from(1)”。 (6认同)

zig*_*tar 28

使用迭代器的解决方案

您也可以使用Iterator而不是a Stream.在Stream保持所有的计算值的引用.因此,如果您计划仅访问每个值一次,则迭代器是一种更有效的方法.但迭代器的缺点是它的可变性.

有一些很好的方便方法可以创建Iterator在其伴随对象上定义的s .

编辑

不幸的是,我没有简短的(支持库)方式来实现类似的东西

Stream.from(1) takeWhile (factorial(_) <= Long.MaxValue) last
Run Code Online (Sandbox Code Playgroud)

Iterator为一定数量的元素推进的方法是:drop(n: Int)dropWhile:

Iterator.from(1).dropWhile( factorial(_) <= Long.MaxValue).next - 1
Run Code Online (Sandbox Code Playgroud)

- 1作品为这个特殊的目的,但不是一个通用的解决方案.但是lastIterator使用pimp我的库上实现一个方法应该没问题.问题是无限迭代器的最后一个元素可能会有问题.所以它应该像lastWith集成的方法一样实现takeWhile.

可以使用以下sliding方式实现丑陋的解决方法Iterator:

scala> Iterator.from(1).sliding(2).dropWhile(_.tail.head < 10).next.head
res12: Int = 9
Run Code Online (Sandbox Code Playgroud)