哎呀!我正在学习 Scala,并正在阅读《Scala 函数式编程》一书。我一直在玩,发现自己处于这样的情况:我希望能够将迭代器列表转换为列表迭代器,我从初始的
List[T]
开始,并有一个创建 T => Iterator[T]
迭代器的函数。我可以将其映射到初始列表并获得 List[Iterator[T]]
,但我最终想将其变成 Iterator[List[T]]
。
我确信我没有解释得那么好,所以这是一个例子:
def collatz(n: Int): Int =
n % 2 match
case 0 => n / 2
case 1 => 3 * n + 1
def collatzes(n: Int): Iterator[Int] =
Iterator.iterate(n)(collatz)
@main def main: Unit =
val inits = List(1, 2)
val iters = inits.map(collatzes)
val iter = ???
// want to turn this list of iterators into an iterator of lists,
// that gives me a list of the _.next of each iterator on each
// call of iter.next
我确信我可以通过某种循环轻松地完成我需要的操作,但很想知道 Scala 3 中是否有一种惯用的函数方法来执行此类型转换。
干杯!
希望不要太简单化,我可能会这样做:
val iter = iters.iterator.map(_.toList)
iterator
方法在所有 Iterable
上定义,包括 List
,正如你可以想象的那样,它返回原始集合的 Iterator
。 map
函数将函数应用于每个嵌套的 Iterator
,将每个嵌套到一个具体列表中。由于 Iterator
是惰性的,只有当你实际使用 Iterator
时,嵌套的 List
才会变成具体的 iter
。
警告一句:
Iterator
很棒,但如果您想使用纯函数式方法,则需要小心处理它们,因为Iterator
被设计为有状态的,导致无法借用的行为本身使函数引用透明,例如:
// The iterator needs to be traversed for the size to be known
// but the process of traversing the iterator moves its internal
// cursor to the end, resulting in the first it.size to be == 1
// and the second one to be == 0
val it = Iterator.iterate(0)(_ + 1).takeWhile(_ < 1)
assert(it.size != it.size)
对于
Iterator
s 的懒惰、记忆化、内置替代方案,您可能想看看 LazyList
s 或 View
s。