将 Scala 3 中的迭代器列表转换为列表迭代器

问题描述 投票:0回答:1

哎呀!我正在学习 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 中是否有一种惯用的函数方法来执行此类型转换。

干杯!

scala functional-programming monads scala-3
1个回答
0
投票

希望不要太简单化,我可能会这样做:

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

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